Search code examples
react-nativereact-context

consuming Context on a Class Component


I'm new to context so may be a very easy error. I'm getting this error when triing to update the context:

[Unhandled promise rejection: TypeError: setUserInfo is not a function. (In 'setUserInfo(newUser)', 'setUserInfo' is undefined)]

Here is what I've done: AppContext.js

import React, { Component } from 'react'

const AppContext = React.createContext();

class UserProvider extends Component {
  // Context state
  state = {
    userInfo: {},
    userChats: {},
    userSettings: {},
  }

  // Method to update state
  setUserInfo = (user) => {
    this.setState((prevState) => ({ user }))
  }
  
  // Method to update state
  setUserChats = (userChats) => {
    this.setState((prevState) => ({ userChats }))
  }
  
  // Method to update state
  setUserSettings = (settings) => {
    this.setState((prevState) => ({ settings }))
  }
  
  render() {
    const { children } = this.props
    const { userInfo } = this.state
    const { setUserInfo } = this
    const { userChats } = this.state
    const { setUserChats } = this
    const { userSettings } = this.state
    const { setUserSettings } = this

    return (
      <UserContext.Provider
        value={{
          userInfo,
          setUserInfo,
          userChats,
          setUserChats,
          userSettings,
          setUserSettings,
        }}
      >
        {children}
      </UserContext.Provider>
    )
  }
}

export default AppContext

export { UserProvider }

Wrapping the App Component:

const defaultProviderValue = {userInfo: {}, userChats: {}, userSettings: {}} 

<AppContext.Provider value = {defaultProviderValue}>
    <Container>
        <AppNavigator />
    </Container>
</AppContext.Provider>

and then finally trying to update it on a class component:

import React, { Component} from 'react';

import AppContext from '../Context/AppContext.js'

class startScreen extends Component {
    static contextType = AppContext
     
    constructor(props) {
        super(props);
        this.state = {
        };
    }

    async componentDidMount() {
        const { userInfo, setUserInfo } = this.context
        
        console.log("CONTEXT!!!!! : " + JSON.stringify(userInfo));
    
        const newUser = { name: 'Joe', loggedIn: true };
        
        setUserInfo(newUser);  // ERROR fired: [Unhandled promise rejection: TypeError: setUserInfo is not a function. (In 'setUserInfo(newUser)', 'setUserInfo' is undefined)]

        console.log("NEW     CONTEXT!!!!! : " + JSON.stringify(userInfo));
    

    }

   render() {
        return(null);
   }
}

export default startScreen;

So how can I solve the error? It seems that can not find the method to update the value, but it's defined.


Solution

  • You are trying to use AppContext but you haven't set anything on itt apart from defaultValues. I guess you would want to use UserProvider and use AppContext within it

    import React, { Component } from 'react'
    
    const AppContext = React.createContext();
    
    class UserProvider extends Component {
      // Context state
      state = {
        userInfo: {},
        userChats: {},
        userSettings: {},
      }
    
      // Method to update state
      setUserInfo = (user) => {
        this.setState((prevState) => ({ user }))
      }
      
      // Method to update state
      setUserChats = (userChats) => {
        this.setState((prevState) => ({ userChats }))
      }
      
      // Method to update state
      setUserSettings = (settings) => {
        this.setState((prevState) => ({ settings }))
      }
      
      render() {
        const { children } = this.props
        const { userInfo } = this.state
        const { setUserInfo } = this
        const { userChats } = this.state
        const { setUserChats } = this
        const { userSettings } = this.state
        const { setUserSettings } = this
    
        return (
          <AppContext.Provider
            value={{
              userInfo,
              setUserInfo,
              userChats,
              setUserChats,
              userSettings,
              setUserSettings,
            }}
          >
            {children}
          </AppContext.Provider>
        )
      }
    }
    
    export default AppContext;
    
    export { UserProvider };
    

    <UserProvider>
        <Container>
            <AppNavigator />
        </Container>
    </UserProvider>
    

    Post this change, you will be able to consume the context correctly