React native: ^0.64.0,
@react-navigation/native-stack: ^6.1.0
@react-navigation/bottom-tabs: 6.0.5
@react-navigation/native: 6.0.2
I have a login screen. If the user passes the login screen the app leads the user to a the main part of the app. This is is the MainScreen with a bottom tab bar. The bottom tab bar gives the user the option to move between EditProfileScreen, SetupsScreen & TipsScreen.
I am setting up the react-navigation in the App.js:
import Context from './src/GlobalUtils/Context' import GlobalState from './src/GlobalUtils/GlobalState'; export default class App extends Component { static contextType = Context; constructor(props) { super(props); this.state = { props: {}, setups: [] } } MainScreen() { return ( <Tab.Navigator initialRouteName="SetupsScreen"> <Tab.Screen name="SetupsScreen" component={SetupsScreen} options={{headerShown: false}} initialParams={{setups: this.context.setups}}/> <Tab.Screen name="Know-How" component={TipsScreen} options={{headerShown: false}} initialParams={{param: this.context.props}}/> <Tab.Screen name="Profile" component={EditProfileScreen} options={{headerShown: false}} initialParams={{param: this.context.props}}/> </Tab.Navigator> ); } render() { return ( <GlobalState> <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Login" component={LoginScreen} options={{headerShown: false}}/> <Stack.Screen name="MainScreen" component={this.MainScreen} options={{headerShown: false}} /> </Stack.Navigator> </NavigationContainer> </GlobalState> ); } }
I am trying to wrap Context API around my react-navigation elements in order to pass the data from the backend call (client/src/Login) to the (client/App.js) file. In order to be able to pass the data to all screens by the initial params. (https://reactnavigation.org/docs/params#initial-params)
My Context.js
import React from 'react'; export default React.createContext({ setups: [], addNewSetup : (setup) => {}, });
My GlobalState.js
import React from 'react'; import Context from './Context'; export default class GlobalState extends React.Component{ state = { setups: [], } addNewSetup = (setup) => { const list = [...this.state.setups, setup]; this.setState({tasks: list}); }; render(){ return ( <Context.Provider value={{ setups: this.state.tasks, addNewSetup: this.addNewSetup, }} > {this.props.children} </Context.Provider> ); } }
And my Login.js
import {GetSetups} from "./Api/Index"; import Context from '../GlobalUtils/Context'; export default class Login extends Component { static contextType = Context; GetSetups(fullUserInfo.user_metadata.bar, fullUserInfo.user_id, this) //Backend call .then(response => this.context.addNewSetup(response)) //Add data to Context API .then(() => this.props.navigation.navigate('MainScreen')); //Navigate to MainScreen }; }
But I can’t navigate to MainScreen because I get the following error:
TypeError: undefined is not an object (evaluating ‘this.context.tasks’)
So this.context.tasks is undefined
in App.js.
How can I make the context not undefined?
Thanks!
Advertisement
Answer
Since you have wrapped your entire navigation container with you can access the context data directly in component/screens
e.g. class component
import React, { Component } from 'react' import UserContext from './UserContext' class HomePage extends Component { static contextType = UserContext componentDidMount() { const user = this.context console.log(user) // { name: 'Tania', loggedIn: true } } render() { return <div>{user.name}</div> } }
functional component
import React, { Component } from 'react' import { UserConsumer } from './UserContext' class HomePage extends Component { render() { return ( <UserConsumer> {(props) => { return <div>{props.name}</div> }} </UserConsumer> ) } }
functional component with hooks
import React, { useContext } from 'react' import UserContext from './UserContext' export const HomePage = () => { const user = useContext(UserContext) return <div>{user.name}</div> }