Home > Software design >  useState not updating nested component
useState not updating nested component

Time:08-29

I have a function that uses a React hook to setup an initial array of users. The array subsequently gets rendered on the screen in the form of a list. Every time a button is clicked, a new element is appended to the end of the array. The update gets rendered to the screen correctly.

I also have another component that receives this array and should for now replicate the same behaviour but unfortunately the update does not get rendered. Code for both below.

I've read about shallow and deep copies but seems that's not the cause because it works in the parent component correctly. I specifically initialise a new array in the setUsers hook to create a new reference. Code for both below:

Parent Component

import { Button, List } from "grommet";
import { Add } from "grommet-icons";
import { useState } from "react";

import Pending from "./Pending";

export default () => {
  const [users, setUsers] = useState([
    { key: 1, name: "Alan", amount: 20 },
    { key: 2, name: "Bryan", amount: 30 },
    { key: 3, name: "Chris", amount: 40 },
    { key: 4, name: "Eric", amount: 80 }
  ]);

  return (
    <>
      <Button
        primary
        label="Add"
        icon={<Add />}
        onClick={(e) => {
          const newUser = {
            key: Date.now(),
            name: "Adam",
            amount: 30
          };
          setUsers((oldUsers) => [...oldUsers, newUser]);
        }}
      />
      <List primaryKey="name" secondaryKey="amount" data={users} />
      <Pending data={users} />
    </>
  );
};

Nested Component

import { useState } from "react";
import { List } from "grommet";

export default (props) => {
  const [users] = useState(props.data);

  return (
    <>
      <List primaryKey="name" secondaryKey="amount" data={users} />
    </>
  );
};

Any ideas for what could be causing this. I'm new to React in general so would appreciate an explanation of why this happens on top of an actual solution.

CodePudding user response:

You took the initial props.data and put in the state. Later, when the props changed, you did not change the state - the users being rendered are still those from the state, rather than the updated ones from the props. That is, if at first you have

props.data === users === [1, 2, 3, 4]

After adding a user you get

props.data === [1, 2, 3, 4, 5] !== [1, 2, 3, 4] === users

In a case like this, you don't need a useState - just render the data from props directly. That was the component will update every time its props change.

import { List } from "grommet";

export default (props) => {
  return (
    <>
      <List primaryKey="name" secondaryKey="amount" data={props.data} />
    </>
  );
};
  • Related