1

I'm new to React and I'm learning, through a simple example, how to use the useContext hook.

Let me briefly explain what I'm doing:

I'm retrieving data from jsonplaceholder and I want to pass the retrieved object, through useContext, to another component (therefore without using props).

The error I get is the following:

'UsersContext' is not defined

The code is the following:

App.js

import React, { useEffect, useState, createContext } from 'react';

export default function App() {
  const [users, setUsers] = useState([]);

  const UsersContext = createContext();

  useEffect(async () => {
    await fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  return (
    <UsersContext.Provider value={users}>
      <h1>Hello</h1>
      <ListUser />
    </UsersContext.Provider>
  )
}

ListUser.js

import ListUser1 from './ListUser1';

export default function ListUser(props) {
    return (
        <>
            <h1>Component ListUser</h1>
            <ListUser1 />
        </>
    )
}

ListUser1.js

import { useContext } from "react";

export default function ListUser1() {
    const users = useContext(UsersContext);
    return (
        <>
            <h1>Component ListUser1</h1>
            {
                users.map((user) =>
                    <h4>{user.name}</h4>)
            }
        </>
    );
}
Sarah
  • 292
  • 1
  • 10

1 Answers1

4

You need to export the context from the file it is defined in (App.js in your case) and import it in the file you are using it from ListUser1.js.

So your App.js could look like this:

import React, { useEffect, useState, createContext } from 'react';
import ListUser from './ListUser' // This import was missing too!

// Create and EXPORT the context here
export const UsersContext = createContext();

export default function App() {
  const [users, setUsers] = useState([]);

  // You can't pass an async function to useEffect (you don't need it anyway!)
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  return (
    <UsersContext.Provider value={users}>
      <h1>Hello</h1>
      <ListUser />
    </UsersContext.Provider>
  )
}

Finally, add this line to ListUser1.js:

import { UsersContext } from "./App";

Notes:

  • Please note I also fixed your useEffect so it doesn't receive an async function.
  • You have a working version of the code here: https://codesandbox.io/s/wonderful-oskar-mh5m8m
  • It's probably a better practice if you define your context in a separate file. This would avoid circular imports
Fernando SA
  • 1,041
  • 1
  • 12
  • 20
  • Short answer is : Take your context declaration outside of your `App` component, else you can't import it and use it somewhere else. – Quentin Grisel Aug 09 '23 at 11:46
  • Perfect. You have been very clear in your answer. I couldn't get a better answer. I want to ask you about async await in fetch. Do we use async and await in axios? when can we use async and await with data fetch? – Sarah Aug 09 '23 at 11:48
  • @Sarah It's better if you open a new question for that. Just a note: I just made your useEffect handler synchronous as it's a valid solution in this specific case. If you want to use async/await inside useEffect, you have to do something like https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret Please, accept the answer if the solution works for you. – Fernando SA Aug 09 '23 at 11:56