2

Scenario:

I have a Login.js that I show as a Modal from multiple screens wherever I have placed the check to see if a user is logged in or not. After the user successfully login I change a key called LoggedIn to 1 from 0 using AsyncStorage. Now when a user successfully logged in and the Modal closes I want to rerender the scree user is on.

As I have a background in iOS, so there we have viewDidAppear that runs every time there is a Modal or user opens another app and comes back to the screen, etc.

So, what would be the equivalent of that in React Native? When a Modal close it should check if the LoggedIn value is changed in AsyncStorage and I've already prepared the components to render accordingly to the value of LoggedIn value.

Code:

I have a screen Profile.js in which I'm checking:

    AsyncStorage.getItem("LoggedIn").then((value) => {
        if (value === "1") {
            setNeedLogin(true)
        } else {
            setNeedLogin(false)
        }
    });

    const [needLogin, setNeedLogin] = useState(false);

Based on the above state I'm rendering the view as:

                {
                    !needLogin &&
                    <View>
                        <Text>{userName}</Text>
                        <Text>{userEmail}</Text>
                        <TouchableOpacity>
                            <Text>Logout</Text>
                        </TouchableOpacity>
                    </View>
                }
                {
                    needLogin &&
                    <View>
                        <Text>You are not logged in</Text>
                        <Text>Please login or create a new account to see more information.</Text>
                        <TouchableOpacity onPress={() => {
                            alert('I am showing login screen here which is a modal')
                        }}>
                            <Text>Login or Sign Up</Text>
                        </TouchableOpacity>
                    </View>
                }

Now when the Login.js renders the Modal and use logs in upon successful login I change the value of LoggedIn to 1 and close the modal which shows the Profile.js screen but when it shows it the view doesn't rerender. So, how would I check and change the state every time the profile.js view appears?

Chaudhry Talha
  • 7,231
  • 11
  • 67
  • 116

3 Answers3

1

An equivalent of viewDidAppear in react native would be componentDidUpdate.

Sounds like you are dealing with 2 different components in the app, a Login and a Modal component.

One way to go about that would be passing a callback method to the Modal component if you extend the reusability of the Modal component.

For example,

class Login extends React.Component {
  
  onLoginDone = props => {
    // do some other things, like authenticate with the props data
  }

  render() {
    <View>
      <Modal onClose={this.onLoginDone} />
    </View>
  }

}

class Modal extends React.Component {

  constructor(props) {
    this.state = {
      isVisible: false
    }
  }

  onClose = () => {
    this.setState({ isVisible: !this.state.isVisible })
    this.props.onClose()
  }

  render() {this.state.isVisible && <View />}
}

Rex Low
  • 2,069
  • 2
  • 18
  • 47
0

Once the user has logged in (when you have validated the login credentials), you can change the state variable needLogin to false, this will re-render the screen, provided the state is connected to the screen that you want to re-render

  • That would work if I'm showing `Login.js` from one screen only. The reason why I made the `Login.js` a `Modal` is that I want to show it from multiple screens. Will, it still works in this scenarios? – Chaudhry Talha Apr 05 '21 at 06:48
  • From where are you opening the modal, is the modal in your root file (app.js)? – Bharath Apr 06 '21 at 07:09
0

First of all, you have to be clear in the mounting and updating process in react-native.

A componennt will re-redner whenever.

  1. Props of the parents get updated.
  2. State of the component gets updated.

Now coming to your problem, your login component will not re-render until the above two conditions fulfilled, and as you are using AsyncStorage it is not reactive too. So either you have to use some reactive storage like redux-persist or you have to use focus listeners, I am assuming that you are using react-navigation so this focus listener might be a good fit for you.

Whenever the focus will be changed this function will be a trigger so you don't need to take care of updating the component etc.

import * as React from 'react';
import { View } from 'react-native';

function ProfileScreen({ navigation }) {
  React.useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      // The screen is focused
      // Call any action
    });

    // Return the function to unsubscribe from the event so it gets removed on unmount
    return unsubscribe;
  }, [navigation]);

  return <View />;
}

https://reactnavigation.org/docs/function-after-focusing-screen/

Note: this focus listener will not work with react-native provided modal then you have to use react-navigation modal

If you don't want to use any focus listener or redux-persist you can simply check while opening the modal.

useEffect(()=>{
   if(modalState){
     AsyncStorage.getItem("LoggedIn").then((value) => {
     if (value === "1") {
        setNeedLogin(true)
     } else {
        setNeedLogin(false)
    }
});
 }
}, [modalState])
Waheed Akhtar
  • 3,110
  • 1
  • 16
  • 30