简体   繁体   中英

React Native child component does not receive updated state from parent

I am trying to implement an app login screen where user enters username and password, and the app would retrieve a Json web token to be stored in application state for managing their account on the server. Now, my App.js looks like the following

const RootStack = StackNavigator(
{
  LoginPage:{screen:LoginPage},
  HomePage:{screen:HomePage},
},
{headerMode:'none'},
);

export default class App extends Component{
constructor(props) {
    super(props);
    this.state = {token:'not available yet'}
}


updateState = async(u,p) => {
    try {
        let token = await this.getToken(u,p);
        let merchantInfo = await this.getMerchantInfo(token);

        this.state = {token: token, merchantInfo}
        console.log(this.state)
        console.log('our token state is '+ this.state.token)
        console.log("our merchantinfo state is "+this.state.merchantInfo.name)
    }
    catch (error) {console.log(error);}
}



// update the state of merchant using authToken
getMerchantInfo = async(authToken) => {
    var options = {
      "method": "GET",
      "headers": {
        "authorization": "Bearer " + authToken,
        "content-type": "application/json"
        }
    }

    try {
        let response = await fetch('http://example.com/merchants/',options);
        let responseJson = await response.json();
        return responseJson;
    } catch (error) {console.error(error);}
}

// send over the username and password to server to retrieve an authToken
getToken = async(u,p) => {
    console.log('username is: '+u+' password is: '+p)
    var options = {
        "method": "POST",
        "headers": {
            "content-type": "application/json"
        },
        "body": JSON.stringify({
            "email": u,
            "password": p,
        }),
    };

    try {
        let response = await fetch('http://example.com/merchants/login',options);
        let responseJson = await response.json();
        return responseJson.token;
    } catch (error) {console.error(error);}
}


render() {
    return (<RootStack screenProps= {this.state} />)
}
}

and my HomePage.js looks like the following

export default class HomePage extends Component {
constructor(props) {
super(props);
this.state = {isReady: false};
console.log ('HomePage gets this token state: ' + this.props.screenProps.token)
}


render() {
return (
  <Container>
    <Header hasTabs>
      <Left />
      <Body>
        <Title>my app</Title>
      </Body>
      <Right>
        <Button transparent onPress={() => this.props.navigation.navigate('LoginPage')}>
          <Text>Logout</Text>
        </Button>
      </Right>
    </Header>

    <Tabs>
      <Tab heading="Issue">
        <IssueTab />
      </Tab>
      <Tab heading="Redeem">
        <RedeemTab />
      </Tab>
      <Tab heading="Settings">
        <SettingsTab />
      </Tab>
    </Tabs>
  </Container>
);
}
}

When I console.log(this.state.token) in App.js, I get the correct JWT token from my server:

our token state is ayJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.fgJuYW3lIjoibG92ZXNoYWNrIiwiZW1haWwiOiJhQGIuY29tIiwiaW1hZ2UiOiJ4cGxvYWRzL0RlZmF1bHQucG8vIiwibWVyY2hhbnLJZCI6IjViMDBjZGZlNzMwODA4NmE0YjZiOWM3NSIsImlhdCI6MTUyNzgwMjU1MywiZXhwIjoxNTU5MzYwMTUzfQ.0QQStfMyDcmYeqeFToei5M4Q35dj43S05NiI0uosXTg

However, when I console.log(this.props.screenProps.token) in HomePage.js, I get the initial state:

HomePage gets this token state: not available yet

I have tried componentWillReceiveProps and a few other approaches from doing searches on here, but nothing works for my situation. How do i get the updated state from App.js from HomePage.js in my situation?

This is my very first post here on StackOverflow. Cheers and thanks in advance!

State can only be set directly, like this.state = { some: 'state' } , inside of a constructor. Outside of the constructor you have to go through the setter this.setState . setState triggers a rerender and the new state will be passed down as expected. See the state docs here .

...
 updateState = async(u,p) => {
        try {
            let token = await this.getToken(u,p);
            let merchantInfo = await this.getMerchantInfo(token);

            this.setState({token: token, merchantInfo})
        }
        catch (error) {console.log(error);}
    }
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM