6

So I recently started using React and am learning the Context Api. The zest of my code is:

export const UsersContext = createContext();
export function UsersProvider(props) {
    const fetchedItem = async function () {
        const data = await fetch('https://jsonplaceholder.typicode.com/users');
        const users = await data.json();
        setUsers(users);
    };
    const [users, setUsers] = useState([]);
    useEffect(function () {
        fetchedItem();
    }, []);

    return (
        <UsersContext.Provider value={[users, setUsers]}>{props.children}</UsersContext.Provider>
    );
}

And I try to import and iterate over the users array like so:

import { UsersContext, UsersProvider } from './UsersContext';
export default function UsersPage() {
    const [users, setUsers] = useContext(UsersContext);
return (
        <UsersProvider>
{users.map(function (user) {
//I do something with user object});}
</UsersProvider>

The issue is this does not work and I am not sure what the terminologies are to search it on the web. I get TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator)) which to me means that users is not an array? But it is as far as I am concerned. Any suggestions for fixing/debugging this?

2 Answers 2

9

You're using useContext outside of the provider, you should use useContext in a child component.

import { UsersContext, UsersProvider } from './UsersContext';
export default function UsersPage() {
  const [users, setUsers] = useContext(UsersContext);
  return (
    <UsersProvider>
      {users.map(function (user) {
        <div key={user.id}>{user.id}</div>
      })}
    </UsersProvider>
  );
}

is the same as

import { UsersContext, UsersProvider } from './UsersContext';
export default function UsersPage() {
  return (
    <UsersContext.Consumer>
      {([users, setUsers]) => (
        <UsersProvider>
          {users.map(function(user) {
            <div key={user.id}>{user.id}</div>;
          })}
        </UsersProvider>
      )}
    </UsersContext.Consumer>
  );
}

as you can see the consumer is not a child of the provider, thus there is nothing provided to it. Consuming it in a child component works.

import { UsersContext, UsersProvider } from './UsersContext';
export default function UsersPage() {
  return (
    <UsersProvider>
      <UsersPageChild />
    </UsersProvider>
  );
}

function UsersPageChild() {
  const [users, setUsers] = useContext(UsersContext);
  return (
    <div>
      {users.map(function(user) {
        <div key={user.id}>{user.id}</div>;
      })}
    </div>
  );
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow. I just wrapped the UsersPage with UsersProvider from the App component and It works. Thanks so much. I read that it had to be a child component but I was considering that everything inside UsersProvider is a child component as the stuff returned from it is = a component but I guess that's not it.
4

This error may come in React when you are destructuring in wrong way.

Change from const [resId] = useParams(); to const {resId} = useParams();

Note: Check the brackets of resId. It could be possible you are using some other Hooks or Objects, but just check these brackets

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.