Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Context API using useContext in React Native is showing a TypeError

I'm attempting to use the modern Context API within React-Native, but I'm getting the following error:

TypeError: TypeError: undefined is not an object (evaluating 'Context._context')

my createDataContext.js:

import React, { useReducer } from 'react'

export default (reducer, actions, defaultValue) => {
    const Context = React.createContext()

    const Provider = ({ children }) => {
        const [state, dispatch] = useReducer(reducer, defaultValue)

        const boundActions = {}
        for (let key in actions) {
            boundActions[key] = actions[key](dispatch)
        }

        return (
            <Context.Provider value={{ state, ...boundActions }}>
                {children}
            </Context.Provider>
        )
    }

    return { Context, Provider }
}

My context.js:

import { AsyncStorage } from 'react-native'
import createDataContext from './createDataContext'

import { 
    LOGIN_FIRST_STEP, 
    LOGIN_SECOND_STEP,
    AUTH_MODAL, 
    SIGNIN_MODAL,
    SIGNUP_MODAL,
} from '../constants'

const INITIAL_STATE = {
    email: '',
    firstName: '',
    lastName: '',
    password: '',
    cardNumber: '',
    expiration: '', 
    CVV: '',
    billingAddress: '',
    authOpen: false,
    signupOpen: false,
    signinOpen: false,
}

const reducer = (state = INITIAL_STATE, { type, payload }) => {
    switch (type) {
        case LOGIN_FIRST_STEP: 
            const { email, firstName, lastName, password } = payload
            return {
                ...state,
                email,
                firstName,
                lastName,
                password,
            }
        case LOGIN_SECOND_STEP: 
            const { cardNumber, expiration, CVV, billingAddress } = payload
            return {
                ...state,
                email,
                cardNumber,
                expiration,
                CVV,
                billingAddress,
            }
        case AUTH_MODAL:
            return {
                ...state,
                authOpen: true,
                signupOpen: false,
                signinOpen: false,
            }
        case SIGNUP_MODAL:
            return {
                ...state,
                authOpen: false,
                signupOpen: true,
                signinOpen: false,
            }
        case SIGNIN_MODAL:
            return {
                ...state,
                authOpen: false,
                signupOpen: false,
                signinOpen: true,
            }
        default:
            return state
    }
}

const login = dispatch => values => {
    dispatch({ type: LOGIN_FIRST_STEP, payload: values })
}

const login2 = dispatch => values => {
    dispatch({ type: LOGIN_SECOND_STEP, payload: values })
}

const auth = disaptch => () => {
    dipatch({ type: AUTH_MODAL })
}

const signin = disaptch => () => {
    dipatch({ type: SIGNIN_MODAL })
}

const signup = disaptch => () => {
    dipatch({ type: SIGNUP_MODAL })
}

export const { Provider, Context } = createDataContext(
    reducer,
    { login, login2, auth, signin, signup },
    { authOpen: false , signinOpen: false, signupOpen: false }
)

package.json:

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@apollo/react-hooks": "^3.1.1",
    "apollo-cache-inmemory": "^1.6.3",
    "apollo-client": "^2.6.4",
    "apollo-link": "^1.2.13",
    "apollo-link-error": "^1.1.12",
    "apollo-link-http": "^1.5.16",
    "apollo-link-state": "^0.4.2",
    "apollo-link-ws": "^1.0.19",
    "apollo-utilities": "^1.3.2",
    "expo": "^34.0.1",
    "formik": "^1.5.8",
    "graphql": "^14.5.6",
    "graphql-tag": "^2.10.1",
    "react": "16.8.3",
    "react-apollo": "^3.1.1",
    "react-dom": "^16.9.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
    "react-native-gesture-handler": "~1.3.0",
    "react-native-maps": "~0.24.0",
    "react-native-reanimated": "~1.1.0",
    "react-native-web": "^0.11.4",
    "react-navigation": "^4.0.6",
    "react-navigation-stack": "^1.8.0",
    "react-navigation-tabs": "^2.5.4",
    "subscriptions-transport-ws": "^0.9.16",
    "yup": "^0.27.0"
  },
  "devDependencies": {
    "babel-preset-expo": "^6.0.0"
  },
  "private": true
}

And finally app.js:

export default App = () => {
  return (
      <ApolloProvider client={client}>
          <ApolloHooksProvider client={client}>
            <ContextProvider>
              <Root />
            </ContextProvider>
          </ApolloHooksProvider> 
      </ApolloProvider>
  )
}

When I attempt to use by importing Context and using the useContext hook:

const {
    state,
    authModal
} = useContext(Context)

the aforementioned error shows. I've tried removing the react-native package and re-installing it with the latest version. I've tried deleting the node modules, clearing the cache, and re-installing them, but none seem to solve the issue.

like image 332
Kevvv Avatar asked Oct 03 '19 23:10

Kevvv


People also ask

Can we use context API in react native?

React Context API provides a easy way to pass data through the component tree without having to pass props down manually at every level. You can find more about the Context API in React documentation. You can use the React Context API with React Native Navigation with a limitation.

Is context API same as useContext?

The useContext is the React hook, used in context API to consume the context state or object. There are two options for getting the context object. We can get the context object from Context Consumer or useContext Hook. UseContext Hook is an exquisite, more excellent way to get the context object with less code.

Why are useContext returns undefined?

If useContext fails to create a context, it'll return undefined because we forgot the wrap our App or component in a ThemeProvider. If everything works fine, we'll return the actual context.


2 Answers

I had the same error and it's because I was importing Context like this:

import {Context} from '...'

INSTEAD OF

import Context from '..'

like image 88
Tallia Avatar answered Oct 17 '22 06:10

Tallia


For me, it was as simple as... I forgot to add the Provider to my main (App.js) file.

like image 44
Kendra Avatar answered Oct 17 '22 05:10

Kendra