AnswerBun.com

React : useEffect updates the state, but does not re-render the view

Stack Overflow Asked by Baudoin Michael on August 20, 2020

I’d like to sort through an array of objects.
But I’m stuck here for a while: when the props filterActivated changes, the state is updated (verified in the browser’s react dev tool), but there is no re-rendering.

I don’t understand why the view is not re-rendered, even when the ideasArray is getting updated.

This is my component :

import React, { useState, useEffect } from 'react'

// Components
import Idea from './Idea'

const IdeasContainer = ({ filterActivated }) => {

    const [ideasArray, setIdeasArray] = useState([]);

    useEffect(() => {
        const getIdeas = async () => {
            try {
                const response = await fetch("http://localhost:3004/api/ideas")
                const data = await response.json()
                setIdeasArray(data)
            } catch (err) {
                console.error('getIdeas error: ', err, err.stack)
            }
        }
        getIdeas();
    }, []);

    useEffect(() => {
        const sorted = (array) => {
            let newArray = array.sort(function (a, b) {
                if (filterActivated === 'scoreAsc') {
                    return a.score - b.score
                }
                else if (filterActivated === 'scoreDesc') {
                    return b.score - a.score
                }
            });
            setIdeasArray(newArray);
        }
        sorted(ideasArray);
    }, [filterActivated, ideasArray]);

    return (
        <div className="ideasContainer">
            {
                ideasArray.map((idea, index) => {
                    return <Idea key={index} dataIdea={idea} />
                })
            }
        </div>
    )
}

export default IdeasContainer;

One Answer

Firstly, your useEffect has a few issues:

Don't reference the ideasArray as a useEffect dependency if you're setting that value inside the useEffect. That will cause infinite loops because when you set the value, the `useEffect gets called again, which sets the value, which calls it again, which sets the value... and so on. If you depend on the previous value to set the new value, pass a setter function to the setIdeasArray function, for example:

useEffect(() => {
  setIdeasArray(oldValue =>
    [...oldValue].sort((a, b) => {
      if (filterActivated === "scoreAsc") {
        return a.score - b.score;
      } else if (filterActivated === "scoreDesc") {
        return b.score - a.score;
      }
    })
  );
}, [filterActivated]);

Notice how I'm also spreading the oldValue into a new array before sorting. This is because Array.sort is not reliably immutable, so in certain situations it will mutate the original data, which we do not want in React.


If state changes, there is always a re-render. React's render cycle is not the same as the DOM changing, but React will still run the component render cycle if props or state changes.

The issue you're having is due to using the index as a key for each idea. Using indexes as keys is a really bad idea.

The whole point of keys is to allow React to identify items in an array without it having to re-render them, so by using the indexes, what you're essentially saying is that the first item (always index 0) never changes. Yes, your state is re-ordered, but React sees that the keys have not changed order, so it does not change the DOM to match.

Keys need to be related to the item (such as a unique id), so that React can identify that item by something unrelated to "its position within an array".

Correct answer by JMadelaine on August 20, 2020

Add your own answers!

Related Questions

Why Linq Distinct() does not work for my ConsultantList?

1  Asked on November 19, 2020 by karim-husein

         

Flutter app: simple way to remember a user to do something

1  Asked on November 19, 2020 by mactrix

 

Loop through a new json object every X seconds

2  Asked on November 19, 2020 by unluckylad

     

why css file was damaged on server

2  Asked on November 18, 2020 by hamid-talebi

   

Java regex not picking up “+”

1  Asked on November 17, 2020 by matt-draft

 

Complete list continuously in an existing df

2  Asked on November 16, 2020 by nms

     

response.getselectedbutton() is not a function?

2  Asked on November 15, 2020 by fishy-apprentice

     

Javascript: How to create a dropdown effect? (Without JQuery)

3  Asked on November 15, 2020 by ilucifer

     

Custom validation rule with request class not working laravel 7

2  Asked on November 14, 2020 by vishal-vaishnav

     

Output using readlines in Python

1  Asked on November 14, 2020 by greg-atamian

   

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP