skip to Main Content

In my React app I have a page which consists of a list of item cards (each a separated component) and on each of those cards I have a table rendered from item’s nested array objects. When I add an element to the nested array in item by creating a new item with updated array and setting the new list of items as state it does not trigger rerender of the table in the child component.
Here is the rough example of the code I have:

Parent component

const Items = () => {
  // Fetching items in useEffect via API call
  const [itemsList, setItemsList] = useState([]);
  
  // This method is called in this component to add row to an item,
  // but I did not include this part to keep the example concise.
  const addRowToItem = (row, itemId) => {
    setItemsList(itemsList.map((item) => {
      if (item.id === itemId) {
        return {...item, rows: item.rows.concat(row)};
      }
      return item;
    }
  }

  return (
    <div>
      {itemsList.map((item) => (
        <ItemCard item={item} />
      )}
    </div>
  );
}

Child component (ItemCard)

const ItemCard = (props) => {
  const [item, setItem] = useState(props.item);

  return (
    <div>
      {item.rows.map((row) => (
        // Table row  
      )}
    </div>
  );
}

2

Answers


  1. You could either use useReducer instead of useState, or clone the state object using the spread operator when assigning the value, like this:

    const addRowToItem = (row, itemId) => {
        setItemsList([...itemsList.map((item) => {
          if (item.id === itemId) {
            return {...item, rows: item.rows.concat(row)};
          }
          return item;
        }])
      }
    
    Login or Signup to reply.
  2. Inside Child component (ItemCard):
    no need to define useState again. you can use the prop directly. remove the second line and:

    {props.item.rows.map((row) => (
        // Table row  
      )}
    

    I created a sandbox for, you check it out:
    https://codesandbox.io/s/spring-breeze-ykzfln?file=/src/App.js

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search