Home > database >  Can't make Context API work on React application, Uncaught TypeError: react__WEBPACK_IMPORTED_M
Can't make Context API work on React application, Uncaught TypeError: react__WEBPACK_IMPORTED_M

Time:06-03

I'm trying to make ContextAPI work on my application, webpack compiles everything, but on the browser I get

Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable

This is the first I'm trying to use ContextAPI in a project.

On index.js

 ReactDOM.render(
    <React.StrictMode>
        <Router>
            <RoutesTree />
        </Router>
    </React.StrictMode>,
    document.getElementById('app')
);

on RoutesTree.js

const DEFAULT_STATE = {
    state: {
        users: [],
        teams: []
    },
    setState: () => {}
};

export const AppContext = createContext(DEFAULT_STATE);

const RoutesTree = () => {
    const [state, setState] = useState(DEFAULT_STATE.state);
    const value = useMemo(
      () => ((state, setState)),
      [state]
    );
  
    console.log('state', state);

    return (
        <AppContext.Provider value={value}>
            <Routes>
                <Route path='/' element={<App />} />
                <Route path='/teams/:id' element={<Team />} />
            </Routes>
        </AppContext.Provider>
    )
}

export default RoutesTree;

on App.js (work in progress)

const App = () => {

  return (
      <>
          <Home />
      </>
  );
}

on Home.js

const Home = () => {
    const [state, setState] = useContext(AppContext);

    useEffect(() => {
        const getTeams = async () => {
            const response = await axios.get(teamsApiUrl);
            
            setState((prevState) => ({
                teams: response.data,
                users: prevState.users
            }));
        }

        getTeams();
    }, [])

Complete error:

Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
    Home webpack://ecore-project/./src/components/Home/Home.js?:32
    React 16
    <anonymous> webpack://ecore-project/./src/index.js?:15
    js http://localhost:8080/main.js:500
    __webpack_require__ http://localhost:8080/main.js:1313
    <anonymous> http://localhost:8080/main.js:2403
    <anonymous> http://localhost:8080/main.js:2405 main.js line 434 > eval:32:78 The above error occurred in the <Home> component:

Home@webpack://ecore-project/./src/components/Home/Home.js?:32:78 App Routes@webpack://ecore-project/./node_modules/react-router/index.js?:922:7 RoutesTree@webpack://ecore-project/./src/components/RoutesTree/RoutesTree.js?:25:76 Router@webpack://ecore-project/./node_modules/react-router/index.js?:860:7 BrowserRouter@webpack://ecore-project/./node_modules/react-router-dom/index.js?:122:7

Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. react-dom.development.js:18572:15
    React 16
    <anonymous> webpack://ecore-project/./src/index.js?:15
    js http://localhost:8080/main.js:500
    __webpack_require__ http://localhost:8080/main.js:1313
    <anonymous> http://localhost:8080/main.js:2403
    <anonymous> http://localhost:8080/main.js:2405 Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
    Home webpack://ecore-project/./src/components/Home/Home.js?:32
    React 13
    <anonymous> webpack://ecore-project/./src/index.js?:15
    js http://localhost:8080/main.js:500
    __webpack_require__ http://localhost:8080/main.js:1313
    <anonymous> http://localhost:8080/main.js:2403
    <anonymous> http://localhost:8080/main.js:2405

webpack compiler:

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.0.100:8080/
<i> [webpack-dev-server] Content not from webpack is served from 'C:\Users\Alvaro\git\ecore-project\public' directory
asset main.js 1.84 MiB [emitted] (name: main)
asset ./index.html 230 bytes [emitted]
runtime modules 27.5 KiB 14 modules
modules by path ./node_modules/ 1.61 MiB 90 modules
asset modules 4.4 KiB
  data:image/svg xml,

CodePudding user response:

Issue

The issue is how you are trying to compute a memoized context value.

const value = useMemo(
  () => ((state, setState)), // <-- not an iterable value!
  [state]
);

It's not exactly what you think it is, and the code blows up in the Home component when it tries to use array destructuring assignment to access the state and state updater function.

const [state, setState] = useContext(AppContext); // <-- tries to access array

() => ((state, setState)) is actually returning the result of a Comma Operator expression. The setState function is what is returned as a memoized value.

Compounding this issue is that the context value was declared to be an object and not an array.

const DEFAULT_STATE = {
  state: {
    users: [],
    teams: []
  },
  setState: () => {}
};

export const AppContext = createContext(DEFAULT_STATE);

Solution

I am certain you meant to memoize an object instead.

const value = useMemo(
  () => ({ state, setState }),
  [state]
);

Now the consumer needs to destructure the object correctly. It's an object, not an array.

const { state, setState } = useContext(AppContext);
  • Related