Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-native pass state globally using redux

In my app, the LoginScreen(fristScreen) could login with facebook and when the user successfully login, the app receives a facebook access token and navigates to the next screen(VerifyScreen). In the VerifyScreen(secondScreen), when I click a button I want to bring the global state facebookToken and display on screen. Below is my code:

App.js

import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { createDrawerNavigator, createStackNavigator, } from 'react-navigation'

const reducer = (state = '', action) => {
  switch (action.type) {
    case 'UPDATE':
            return { facebookToken: action.payload}
  }
    return state
}

const store = createStore(reducer)

class App extends Component {
  render(){
    return(

      <Provider store={store}>
        <View style={{flex:1,backgroundColor:'transparent'}}>
          <AppDrawerNavigator/>
        </View>
      </Provider> 
    )
  }
}

LoginScreen.js

import { LoginButton, AccessToken } from 'react-native-fbsdk';
import {connect} from 'react-redux'

class LoginScreen extends Component{

  <View>
            <LoginButton
              onLoginFinished={
                (error, result) => {
                  if (error) {
                    console.log("login has error: " + result.error);
                  } else if (result.isCancelled) {
                    console.log("login is cancelled.");
                  } else {
                    this.props.navigation.navigate('VerifyScreen')
                    AccessToken.getCurrentAccessToken().then(
                      (data) => {
                        this.setState({facebookToken:data.accessToken},
                    () =>  console.log('facebookToken.state',this.state.facebookToken),
//Here I am getting undefined for 'this.props.facebookToken'                        
() =>  console.log('facebookToken.props',this.props.facebookToken),
                        console.log('facebook login success!'),
                        console.log('facebook token is:',data.accessToken.toString()))
                      }
                    )
                  }
                }
              }
              onLogoutFinished={() => console.log("logout.")}/>

//I created a button to see if I could call global state. but this would give me an error "state is not defined"
<Button
            title="call global state"
            onPress={() => this.props.increaseCounter()}/>


</View>

function mapStateToProps(state) {
    return {
        facebookToken: state.facebookToken
    }
}

function mapDispatchToProps(dispatch) {
    return {
        increaseCounter: () => dispatch({ type: 'UPDATE',payload: state.facebookToken }),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen)

VerifyScreen.js

import React, { Component } from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
import {connect} from 'react-redux'


class VerifyScreen extends Component {
    render() {
        return (
        <View>
          <Button
                  title="Get facebook Access Token"
                  onPress={()=>  
                   //I get undefined data when I console.log
         console.log(this.state.facebookToken,'this.state.facebookToken')}/>
          <Text style={{ fontSize: 20 }}>{this.props.facebookToken}</Text>
        </View>
        );
    }
}

function mapStateToProps(state) {
    return {
        facebookToken: state.facebookToken
    }
}

export default connect(mapStateToProps, null)(VerifyScreen)

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    }
});

In my LoginScreen, when I console.log this.state.facbookToken I get the data, but when I navigate to the nextScreen(VerifyScreen) and console.log it, I get undefined.

My question: how could I call global state from the VerifyScreen? I am very new to redux so I might be doing things wrong. Any advise or comments would really help. Thanks in advance!

like image 669
kirimi Avatar asked Oct 16 '22 12:10

kirimi


1 Answers

In your verify screen, you try to console log this.state.facebookToken which definitely undefined. Instead try to update the code to this.props.facebookToken

console.log(this.props.facebookToken,'this.props.facebookToken')}/>

this.state is meant to hold component level state, when you talk about global state, redux state are sitting in this.props.xxx depending on the mapStateToProps method you defined

UPDATES:

The problems that you're violating is,

You're not passing payload to reducer when you dispatch action

increaseCounter: ()=>dispatch({ type: 'UPDATE', payload: state.facebookToken })

Then in your App.js, you have the following code

switch (action.type) {
  case 'UPDATE':
    return { facebookToken: state.facebookToken}
}

If you look at the code above, u can notice that Redux's flow work like this, we try to dispatch an action, which is an action object with two property, type and payload (payload is optional, or u can name it whatever you like), then in your reducer, you can access the payload as below

switch (action.type) {
  case 'UPDATE':
    return { facebookToken: action.payload };
}

you might be wondering what is action.payload, which we provide the value when we dispatch earlier dispatch({ type: 'UPDATE', payload: state.facebookToken }), so action.payload simply is state.facebookToken

Extra:

Depending on your use case of course, but typically when we return a state in reducer, we would want to return all the other states, and only update the particular states that is changed, for example as below:

console.log(action);
switch (action.type) {
  case 'UPDATE':
    return { ...state, facebookToken: state.facebookToken };
}

Often when I'm trying to debug the problem with Redux, I will do a console.log before the switch statement to find out what are the type i'm dispatching, and the payload I'm passing, and hence console.log(action) which you will be able to see the type property, and the value of payload property

like image 114
Isaac Avatar answered Nov 03 '22 09:11

Isaac