skip to Main Content

I have a page for listing products in a table, each row of the table has checkbox who meant to toggle the row’s active (Boolean) state when it clicked. The problem is that after updating the state the DOM doesn’t change.
This how my code looks like:

const [products, setProducts] = useState([]);

useEffect(() => {

    fetchProducts(); //fetch the products from the server

}, []);


const productChecked = (index) => { 
    setProducts((prevState) => {
        const newState = prevState;
        newState[index].active = !newState[index].active;
        return newState;
    });
};

...

{products.map((product, index) => {
    ...
    <td>
        <input type="checkbox" checked={!product.active} onClick={() => productChecked(index)}/>
    </td>
    ...
})}

I added this useEffect to test it, but it doesn’t seem to work at all (I can’t see this console log):

useEffect(() => {
    console.log('products',products);
}, [products]);

I can’t understand why it is happening… what am I missing here?

Thanks in advance 🙂

3

Answers


  1. In your code, you are trying to assign prev array to new array which is not changing the reference thus not re-rendering the component.

    So in order to re render it you’ll have to change the reference

    You can also try this approach this will reduce the dependency on callback and prevState.

    const productChecked = (index) => {
      let newProducts = [...products];
      newProducts[index].active = !products[index].active;
      setProducts(newProducts);
    

    };

    Login or Signup to reply.
  2. When you want to update the state and trigger a rerender, you should create a new object or array that represents the updated state, rather than modifying the existing state object directly.

    const productChecked = (index) => { 
        setProducts((prevState) => {
            // Create a shallow copy of the previous state array
            const newState = [...prevState];
    
            // Toggle the 'active' property of the product at the specified index
            newState[index] = {
                ...newState[index], // Copy the existing product properties
                active: !newState[index].active, // Toggle the 'active' property
            };
    
            return newState;
        });
    };
    
    Login or Signup to reply.
  3. To fix this issue, you should create a new copy of the products array before updating the state. You can do this by using the spread operator or slice method to clone the array. Here’s the modified productChecked function:

      const productChecked = (index) => {
          setProducts((prevState) => {
            const newState = [...prevState]; // Create a new array copy
            newState[index].active = !newState[index].active;
            return newState;
          });
        };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search