React:useEffect更新状态,但不重新渲染视图

时间:2020-08-03 20:51:51

标签: reactjs rendering use-effect

我想对一组对象进行排序。 但我在这里停留了一段时间:当道具filterActivated更改时,状态会更新(在浏览器的react dev工具中进行了验证),但是没有重新渲染。

我不明白为什么即使更新ideasArray也不重新渲染视图。

这是我的组件:

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;

1 个答案:

答案 0 :(得分:0)

首先,您的useEffect存在一些问题:

如果您在useEffect内设置该值,请不要将ideaArray视为useEffect依赖项。这将导致无限循环,因为当您设置值时,会再次调用`useEffect,它会设置值,然后会再次调用它,然后再设置值...依此类推。如果您依靠先前的值来设置新值,则将setter函数传递给setIdeasArray函数,例如:

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]);

在排序之前,请注意如何将oldValue散布到新数组中。这是因为Array.sort并不是可靠地不可变的,因此在某些情况下它将使原始数据发生突变,而我们在React中是不希望的。


如果状态发生变化,则始终会进行重新渲染。 React的渲染周期与DOM更改不同,但是如果prop或状态发生变化,React仍将运行组件的渲染周期。

您遇到的问题是由于每个想法都将index用作key。使用索引作为键是一个非常糟糕的主意。

键的全部要点是允许React无需重新渲染数组即可识别数组中的项目,因此,使用索引,您实际上要说的是第一项(总是索引{{1 }})永不改变。是的,您的状态已重新排序,但是React认为密钥没有更改顺序,因此它不会更改DOM以匹配。

键需要与项目相关(例如唯一ID),以便React可以通过与“其在数组中的位置”无关的识别该项目。