Code push is showing memory leak in the react native app - react-native

I am using code push for my app but it is showing me memory leak
useEffect(() => {
checkforupdate();
}, []);
async function checkforupdate() {
codePush.sync(
{
installMode: codePush.InstallMode.ON_NEXT_RESTART,
},
checkdata,
);
}
function checkdata(syncStatus) {
switch (syncStatus) {
case codePush.SyncStatus.CHECKING_FOR_UPDATE:
break;
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
break;
case codePush.SyncStatus.AWAITING_USER_ACTION:
break;
case codePush.SyncStatus.INSTALLING_UPDATE:
break;
case codePush.SyncStatus.UP_TO_DATE:
break;
case codePush.SyncStatus.UPDATE_IGNORED:
break;
case codePush.SyncStatus.UPDATE_INSTALLED:
break;
case codePush.SyncStatus.UNKNOWN_ERROR:
break;
default:
null;
}
}s
what is the issue in this i am not able to get it. As i have checked with all functions but it is giving me memory leak on app start. In this checkdata() is calling 2 times i think i don't know why and i think so that my other function is call again.
Error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function

Related

Cannot Prevent Async on GraphQL Mutation and Recoil State updating process

I am working on a Chat Room portion of a larger React Native app and am facing issues with the updating of the page after a text has been sent. Currently, when the user compiles a text in a TextInput and hits the send button, it triggers a mutation that is supposed to add a message object to the chatroom model, which is linked to all of the users that are currently in the chatroom. It is then supposed to take the result from this mutation, which is the updated chatroom connected to all the users (the current user included obviously) and render its contents. It is intended to rerender the page after the activeThread atom is updated, since the page used the contents of activeThread to render everything on the page, new messages included. However, this occurs asyncronously and it tries to render a promise.... which you can't do. I've tried everything I'm capable of, using thens and awaits everywhere I could but JavaScript's giving me the middle finger pretty hard on this one. My code is below...
const handleSendMessage = async () => {
console.log(activeThread.id)
if (newMessage.length > 0){
return sendMessage({
variables: {
chatroomId: activeThread.id,
content: newMessage
}
}).then( async (newMessageThread) => {
await setUpdating(true)
await setNewMessage("")
await setKeyboardVisible(false);
await setActiveThread(newMessageThread)
}).then( async() => {
await console.log(activeThread)
await setUpdating(false)
})
}
else{
}
}
setUpdating is part of a useState. This is defaulted to false and when true the main page is not set to render. It is intended as a guard against attempting to render the promise. Didn't work, obviously
setNewMessage is defaulted to "" and is responsible for keeping track of the text the user has entered into the TextInput. Pretty irrelevant here.
setKeyBoardVisible is pretty self explanatory and also not necessary
setActiveThread is the heavy lifter here. Pretty much all of the contents rendered are going to be pulling data from activeThread, which is, again; a recoil state. For example, everything below looks essentially something like
<View>
<Text> {activeThread.someMethodOrValue} </Text>
</View>
I can only assume this has something to do with the async-ing. I have a console.log(error) statement in my backend GraphQL mutation resolver that would catch any errors there, and it's not triggering anything. The error I get everytime is the following...
TypeError: undefined is not an object (evaluating 'activeThread.chatroomName.split')
This error is located at:
in MessageThread (created by SceneView)
in StaticContainer
in EnsureSingleNavigator (created by SceneView)
in SceneView (created by SceneView)
in {/* keeps going down the stack you get the idea */}
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'activeThread.chatroomName.split')]
at Pages/CommunicationPage/MessageThread.js:210:37 in MessageThread
Any solutions?
While the code I had still looks like it should work to me, we all know how finnicky code can be sometimes. What ended up working was separating the handleSendMessage function and the mutation, creating a whole new function for the mutation.
My new code looks like this...
const handleSendMessage = () => {
if (newMessage.length > 0){
handleMutation().then( (resolved) => { // This line fixed all the promise issues
setNewMessage("") // clears current message input
let newActiveThread = resolved.data.driverSendMessage.chatroom // creates new thread JSON from mutation data
console.log(newActiveThread) // testing out a different bug now lolllll
setActiveThread(newActiveThread) // Sets current thread to match the new one
// changes the entire user state, leaving all over threads untouched but updating the current one
let updatedThreads = [newActiveThread]
user.chatrooms.forEach( (chat) => {
if (chat.id == newActiveThread.id){
console.log("Skipping " + newActiveThread.chatroomName)
}
else {
updatedThreads.push(chat)
}
})
// changes the main recoil state
setUser({...user, chatrooms: updatedThreads})
})
}
else{
// Throw Error Handling for no input or just do nothing, we'll see
}
}
const handleMutation = async () => {
return sendMessage({
variables: {
chatroomId: activeThread.id,
content: newMessage
}
})
}

How to wait for a dispatch to end before continuing runtime

I'm building an app using React Native, and I have the following code
sumbit_answer(answer) {
this.setState({isLoading: true})
if (this.props.curr_round_correct_answer == '') {
this.props.dispatch(insert_correct_answer(answer));
//replace
} else {
this.props.dispatch(insert_answer(this.props.current_player, answer));
}
if (
this.props.curr_round_results.length ==
this.props.players_names.length - 1
) {
this.props.navigation.replace('RoundStatistics');
} else {
this.props.navigation.replace('PassPlayer');
}
}
Basically I want to run the second if statement only when the dispatch from the previous if is completed, that is currently not happening. The dispatch does not make any API calls, only changes to the redux state. So how can I prevent this from happening? I though about using the await keyword, but does not feel right.Thanks!!!
This is a somewhat opinionated answer, but I think the best way to handle this is to move the second section elsewhere and make it conditional based on a combination of local state and selectors. You can call it within a useEffect hook.
You should be able to tell the dispatch has completed and when you are ready for the next step by looking at the redux state. You can also use local state to store boolean flags like didSubmitAnswer if needed. Somehow you combine that information into an isCompletedRound boolean. Your useEffect hook fires the navigation actions if isCompletedRound === true.

Where do I listen for login status in React Native login view?

I've written a login component that works great except I can't figure out the proper way to move to the login page when login is successful.
I know it will somehow involve:
if (this.props.user) {
this.props.navigation.navigate("Main");
// I'm using react-native-navigation. But any implementation of "now go to the home page" would go here.
}
I've tried putting that at the top of my render method, which works, but I do get an error/warning (error in the debug console, warning in the simulator) saying "Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state."
Makes sense. But I can't conceive of the actual proper place to put it.
PS I tried this but it didn't work at all (navigation doesn't occur)
shouldComponentUpdate() {
if (this.props.user) {
this.props.navigation.navigate("Main");
return false;
}
return true;
}
Your last method is almost correct
shouldComponentUpdate() {
if (this.props.user) {
this.props.navigation.navigate("Main");
return false;
}
return true;
}
However, you're using this.props, which are the old props before the update. The new props are passed as the first argument to the method. It's also recommended to use componentWillReceiveProps over shouldComponentUpdate in this particular case as shouldComponentUpdate was introduced to prevent the component from updating.
So, this would make something like this:
componentWillReceiveProps(newProps) {
if (newProps.user) {
this.props.navigation.navigate("Main");
}
}

React Native Expo: Cannot add child that doesn't have a YogaNode - Error on Android

I am stuck with this error:
Cannot add a child that doesn't have a YogaNode to a parent without a measure function!
(Trying to add a 'ReactRawTextShadowNode' to a 'LayoutShadowNode')
The app is on expo and works fine in iOS
but on Android I always get this error when pressing the button for authentication.
Earlier it was working fine, I tried to reset my commits to track the error but for no help.
I think, whenever this function is executed, the error arises:
onButtonPress = async () => {
const { code } = this.props;
await this.props.loginUser({ code });
if (this.props.error) {
await AsyncStorage.removeItem('code');
this.props.navigation.goBack();
} else {
await AsyncStorage.setItem('code', code);
await this.props.orderUpdate();
await this.props.menuFetch();
this.props.navigation.navigate('main');
}
};
Note that the props are accessing redux state and calling redux actions.
This issue having a different reason:
Might be the comments inside the render method of component so try to remove comments inside render method of component component.
Might be because of that you have not closed a tag correctly
Might be using of && operator inside render method so remove '&&'
operator and use ternary operator.
Instead { foobar && <View/> }
Use this { foobar ? <View/> : null }

state get null after disptach

I am using redux in my react native project and I get this error when dispatched sth.
error:
TaskQueue: Error with a task: Invariant Violation: Invariant Violation: Invariant Violation: Tried to get the frame for out of range index NaN
extra information which I prefer to say is that I have navigation with the first screen has connected to *that list and the second screen is connected to *room_Messages
My Reducer:
case 'RECEIVE_MESSAGE':
{
index=0;
msg = JSON.parse(action.msg)
msgItem = {
id: Math.random(),
message: msg.message
}
return {...state,
chatList: {
...state.chatList
, [0]: {
...state.chatList[0], room_messages: {
...state.chatList[0].room_messages.slice(0)
}
}
},
}
when I navigate to the second screen and then dispatch RECEIVE_MESSAGE action, in the first screen my props get null(i noticed this in componentDidUpdate of the first screen)