Home > other >  React object undefined on render
React object undefined on render

Time:04-08

I have an API that responds with the following object:-

[
  {
     "A":4,
     "B":3,
     "C":2,
     "D":1,
  }
]

I want to display the object data in the following component:-

export default function name() {
  const dispatch = useDispatch();

  const { postsInfo } = useSelector((state) => state.posts);

  useEffect(() => {
    dispatch(getPostsInfo());
  }, [dispatch]);

  console.log(postsInfo[0]);

  return (
    <>
      <div className="db-wrapper">
        <div className="cards-container">
          <Card title={"A"} value={postsInfo[0].A} />
          <Card title={"B"} value={postsInfo[0].B} />
          <Card title={"C"} value={postsInfo[0].C} />
          <Card title={"D"} value={postsInfo[0].D} />
        </div>
      </div>
    </>
  );
}

but whenever the page is rendered it throws an error in the console log and nothing is shown on the page.

Uncaught TypeError: Cannot read properties of undefined (reading '0')

CodePudding user response:

This is happening because it's an asynchronous process and is being mounted before useEffect ends fetching the data and populates its state.

To deal with it you can use Optional Chaining: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Array item access with optional chaining:

let arrayItem = arr?.[42];

Your component return will be like this:

return (
    <>
      <div className="db-wrapper">
        <div className="cards-container">
          <Card title={"A"} value={postsInfo?.[0].A} />
          <Card title={"B"} value={postsInfo?.[0].B} />
          <Card title={"C"} value={postsInfo?.[0].C} />
          <Card title={"D"} value={postsInfo?.[0].D} />
        </div>
      </div>
    </>
  );

CodePudding user response:

Welcome to asynchronous programming!

Dispatch and useEffect are asynchronous. This means that the render function continues to execute without waiting for the effect callback to complete and the dispatch to populate your redux state. As a result postsInfo is undefined on the initial render, and is only later populated on subsequent renders when the redux state changes.

Whenever you are initializing state in a react component via an asynchronous operation, your render function needs to correctly handle the state being uninitialized. The 'standard' way to do this is to return null if the state is uninitialized, like so:

if (!postsInfo) return null;
  • Related