React Native using Expo changed logged in user suddenly - react-native

I'm building a small social media app using React Native, Expo, Redux and firebase.
I created multiple user accounts for testing, i logged in the app using one of them, while i was working on the app, it suddenly changed the user account I logged in with to another user!
Is it normal? If not, what would be the reason for that??
Here's how the registration is being handled:
export class Register extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
name: '',
lastname: '',
degree: '',
description:''
}
this.onSignUp = this.onSignUp.bind(this)
}
onSignUp(){
if(
this.state.email != '' &&
this.state.password != '' &&
this.state.name != '' &&
this.state.lastname != ''
){
const { email, password, name, lastname, degree, description } =
this.state;
firebase.auth().createUserWithEmailAndPassword(email, password)
.then((result) => {
firebase.firestore().collection("Doctors")
.doc(firebase.auth().currentUser.uid)
.set({
name,
email,
lastname,
degree,
description
})
console.log(result)
})
.catch((error) => {
console.log(error)
})
}
else{
alert("Make sure you filled all the fields with correct info!");
}
And Here's the App.js
export class App extends Component {
constructor(props) {
super(props)
this.state = {
loaded: false,
}
}
componentDidMount() {
firebase.auth().onAuthStateChanged((user) => {
if (!user) {
this.setState({
loggedIn: false,
loaded: true
})
} else {
this.setState({
loggedIn: true,
loaded: true
})
}
})
}
render() {
const { loggedIn, loaded } = this.state;
if (!loaded) {
return (
<View></View>
)
}
if (!loggedIn) {
return (
<View></View>
);
}
const onAuthStateChangedUnsubscribe =
firebase.auth().onAuthStateChanged(async (user) => {
if (user) {
// -> Alert Email Verification
await user.sendEmailVerification()
const onIdTokenChangedUnsubscribe =
firebase.auth().onIdTokenChanged((user) => {
const unsubscribeSetInterval = setTimeout(() => {
firebase.auth().currentUser.reload();
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true)
}, 10000);
if (user && user.emailVerified) {
clearInterval(unsubscribeSetInterval) //delete interval
onAuthStateChangedUnsubscribe() //unsubscribe onAuthStateChanged
// -> Go to your screnn
return onIdTokenChangedUnsubscribe() //unsubscribe
onIdTokenChanged
}
})
}
})
return (
<View></View>
)
}
}

Related

Why is InterstitialAd not loaded after the first trigger?

I manage to get the first ad to show, but app crashed the next time I try to trigger an ad. And gives me this error: Error: InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown
In App.js
componentDidMount() {
const eventListener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
setLoaded: true,
});
}
});
interstitial.load();
eventListener();
}
showAds = () => {
interstitial.show();
// No advert ready to show yet
if (!this.state.loaded) {
console.log('null');
return null;
}
};
// This trigger is within another function
this.showAds();
I have a class component so I use ComponentDidMount instead of useEffect. Might that cause some troubles?
UPDATE:
this.state = {
loaded: false,
setLoaded: false,
Listener: null,
};
The above state is an attempt to redo
const [loaded, setLoaded] = useState(false);
constructor () {
super();
this.Listener=null
}
componentDidMount() {
this.Listener = interstitial.onAdEvent(type => {
if (type === AdEventType.LOADED) {
this.setState({
loaded: true,
});
}else if(type === AdEventType.CLOSED){
this.loadAd()
}
});
this.loadAd()
}
componentWillUnmount(){
if(this.Listener!==null){
this.Listener()
}
}
loadAd = () =>{
this.setState({
loaded: false,
});
interstitial.load();
}
showAds = () => {
if (!this.state.loaded) {
console.log('null');
return null;
}else{
interstitial.show();
}
};

How can I make the user always logged in? React Native

Using the code below, how do I get the user to be logged in every time the user opens the application?
export default class LoginScreen extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
userLogin = () => {
if(this.state.email === '' && this.state.password === '') {
Alert.alert('Enter details to signin!')
} else {
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
console.log(res)
console.log('User logged-in successfully!')
Alert.alert('Succesfully logged')
this.setState({
email: '',
password: ''
})
this.props.navigation.navigate('Home')
})
.catch(error => this.setState({ errorMessage: Alert.alert('Not logged') }))
}
}
I'm trying to make a fashion application that includes a profile.
After that, I'm going to put the sign-out but it's already quite clear to me how to do it.
Thanks!!
firebase authentication keeps user signed in
check for login information in componentDidMount using
firebase.auth().onAuthStateChanged((user)=>{
})
if user exists navigate to home screen

React Native navigate not updating props

I have one page with a list of "tenants". When I select one tenant if shows the data for this specific tenant. It is working. However, when I navigate back to the tenant list and select another tenant, it does not update the this.props with the new tenant data.
My Tenant Details Page
constructor(props) {
super(props);
this.state = {
tenantData: {}
};
}
componentDidMount() {
this.getTenantID();
}
componentDidUpdate(prevProps) {
// needs to be a unique value
if (prevProps.tenantData.Email !== this.props.tenantData.Email) {
this.getTenantID();
}
}
getTenantID = async () => {
const { navigation } = this.props;
const tenantID = navigation.getParam('tenantID', '0');
await this.props.getTenantByID(tenantID); // Wait for action to complete
this.setState({
tenantData: this.props.tenantData
});
};
My action:
export const getTenantByID = (tID) => {
return (dispatch) => {
axios.get('http://myirent.com/rent/components/iRentApp.cfc', {
params: {
method: 'getTenantByTenant',
tenantID: tID
}
}).then((response) => {
const tenant = response.data.DATA[0];
console.log(tenant);
const getTenant = {
FirstName: tenant[1],
LastName: tenant[2],
Email: tenant[5],
Phone: tenant[6],
Unit: tenant[11],
MiddleName: tenant[3],
RentalAmount: tenant[4],
MoveInDate: getFormattedDate(tenant[7]),
MoveOutDate: getFormattedDate(tenant[8]),
LeaseStartDate: getFormattedDate(tenant[9]),
LeaseEndDate: getFormattedDate(tenant[10])
};
dispatch({
type: GET_TENANT_DATA,
payload: getTenant
});
});
};
};
The tenantID is being updated and the action response data too. It looks like that the page is loading before updating the this.props.tenantData
The componentDidUpdate() is called immediately after the update. This method is not called in the first rendering.
componentDidUpdate(prevProps) {
// typical use cases (don't forget the props comparison)
if (prevProps.navigation !== this.props.navigation) {
const data = this.props.navigation.getParam('tenantID', '0')
this.getTenantID(data);
}
}
getTenantID = async () => {
const { navigation } = this.props;
const tenantID = navigation.getParam('tenantID', '0');
const tenantdata = await this.props.getTenantByID(tenantID); // Wait for action to complete
this.setState({
tenantData: tenantdata,
updateid : tenantID
});
};

Pusher chatKit onMessage hook fails in Expo app

I am using React Native with Expo, and I am able to create users + rooms and send messages to them with the following code:
const hooks = {
onMessage: message => {
console.log("message", message);
this.setState({
messages: [...this.state.messages, message]
});
},
onUserStartedTyping: user => {
this.setState({
usersWhoAreTyping: [...this.state.usersWhoAreTyping, user.name]
});
},
onUserStoppedTyping: user => {
this.setState({
usersWhoAreTyping: this.state.usersWhoAreTyping.filter(
username => username !== user.name
)
});
},
onPresenceChange: () => this.forceUpdate()
};
class SetupChatKit extends React.Component {
constructor(props) {
super(props);
this.state = {
chatManager: null,
currentUser: {},
currentRoom: {},
messages: [],
usersWhoAreTyping: []
};
}
componentDidMount() {
const { userId, name } = this.props;
this.instantiateChatManager(userId);
this.createChatKitUser({ userId, name });
}
joinOrCreateChatKitRoom = (mode, chatKitRoomId, title) => {
const { chatManager } = this.state;
return chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser });
if (mode === "join") {
return currentUser.joinRoom({ roomId: chatKitRoomId, hooks });
}
return currentUser.createRoom({
name: title,
private: false,
hooks
});
})
.then(currentRoom => {
this.setState({ currentRoom });
return currentRoom.id;
})
.catch(error => console.error("error", error));
};
instantiateChatManager = userId => {
const chatManager = new Chatkit.ChatManager({
instanceLocator: "v1:us1:9c8d8a28-7103-40cf-bbe4-727eb1a2b598",
userId,
tokenProvider: new Chatkit.TokenProvider({
url: `http://${baseUrl}:3000/api/authenticate`
})
});
this.setState({ chatManager });
};
My problem is that console.log("message", message); never gets called, even when I manually add messages to the room via the online control panel.
I've tried logging from chatManager, and that looks like the following:
As you can see from the documentation, the onMessage hook needs to be attached on subscribeRoom, not when joining a room.
https://docs.pusher.com/chatkit/reference/javascript#connection-hooks
So probably add subscribeToRoom() after the first success promise in your joinOrCreateChatKitRoom() method.
I refactored the code with async/await and used .subscribetoRoom() like so:
joinOrCreateChatKitRoom = async (mode, chatKitRoomId, title) => {
const { chatManager } = this.state;
try {
const currentUser = await chatManager.connect();
this.setState({ currentUser });
let currentRoom;
if (mode === "join") {
currentRoom = await currentUser.joinRoom({
roomId: chatKitRoomId
});
} else {
currentRoom = await currentUser.createRoom({
name: title,
private: false
});
}
this.setState({ currentRoom });
await currentUser.subscribeToRoom({
roomId: currentRoom.id,
hooks: {
onMessage: message => {
this.setState({
messages: [...this.state.messages, message]
});
},
onUserStartedTyping: user => {
this.setState({
usersWhoAreTyping: [...this.state.usersWhoAreTyping, user.name]
});
},
onUserStoppedTyping: user => {
this.setState({
usersWhoAreTyping: this.state.usersWhoAreTyping.filter(
username => username !== user.name
)
});
},
onPresenceChange: () => this.forceUpdate()
}
});
return currentRoom.id;
} catch (error) {
console.error("error creating chatManager", error);
}
};

optimistic update for like/dislike and like count with react native, redux

I am building simple video with like/dislike capability like
this
but its not working properly when like or dislike rejected because in componentDidUpdate its going to loop and I dont know what condition should I use to prevent from that.
This is my component:
class PlayingVideo extends Component {
constructor(props) {
super(props);
this.state = {
likedThis: _.includes(this.props.video.likedBy, this.props.user_id),
likedLength: this.props.video.likedBy.length
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.likeVideoHasError) {
this.setState({
likedThis: false,
likedLength: this.state.likedLength - 1
});
}
if (this.props.dislikeVideoHasError) {
this.setState({
likedThis: true,
ikedLength: this.state.likedLength + 1
});
}
}
like = () => {
if (this.props.likeVideoPending || this.props.dislikeVideoPending) return;
this.setState({ likedThis: true, likedLength: this.state.likedLength + 1 });
this.props.dispatch(likeVideo(this.props.videoId));
};
dislike = () => {
if (this.props.likeVideoPending || this.props.dislikeVideoPending) return;
this.setState({
likedThis: false,
likedLength: this.state.likedLength - 1
});
this.props.dispatch(dislikeVideo(this.props.videoId));
};
}
const mapStateToProps = (state, ownProps) => {
return {
likeVideoHasError: state.video.likeVideoHasError,
dislikeVideoHasError: state.video.dislikeVideoHasError,
likeVideoPending: state.video.likeVideoPending,
dislikeVideoPending: state.video.dislikeVideoPending
};
};
export default connect(mapStateToProps)(PlayingVideo);