【问题标题】:How to ensure parent component passes the same prop function to child to avoid rerender如何确保父组件将相同的 prop 函数传递给子组件以避免重新渲染
【发布时间】:2020-06-30 02:52:36
【问题描述】:

目前我设置了两个组件,其中父级呈现一些数据并处理检索,而子级是一个过滤器。此过滤器允许用户按状态或关键字进行过滤。没什么特别的。

现在这是一个分页系统。在父母对数据进行初始请求后,如果他们想要更多,他们会获得下一页 ID 来请求。但是如果过滤器更新了,这个下一页 ID 需要被清除,因为它不好。

所以我所做的就是将一个名为updateFilter() 的函数从父级传递给子级。如果过滤器组件的状态有更新,它会调用父组件并运行updateFilter()。更新的值之一包含在 useEffect() 依赖数组中,因此父级然后使用新过滤器请求新数据。很简单。

问题在于设置孩子的useEffect()。 Eslint 告诉我需要将props.updateFilter 添加到依赖数组中,虽然我可以忽略这一点,但我觉得这样做是错误的。但是父级有相当多的状态会更新,当它更新时,它会将updateFilter() 的新副本向下传递给子级,这会导致它错误地触发。

我该如何解决这个问题?我可以告诉孩子只使用这个函数的静态版本吗?还是我只是从依赖数组中排除props.updateFilter?下面是我的组件的粗略伪代码。

Parent {
    const [stateVal, setStateVal] = useState(...);
    
    function updateFilter(filterStatus) {
        ...
        setStateVal(filterStatus);
    }

    useEffect(() => ..., [stateVal]);

    return <Child updateFilter={updateFilter} />
}

Child {
    const [filterStatus, setStatus] = useState(...);

    useEffect(() => {
        props.updateFilter(filterStatus);
    }, [filterStatus] // Adding `props` here is what I think I should do, but that causes the issue. Apparently the `props` val changes every time Parent's state changes
   
    return ( ... );
}

【问题讨论】:

  • "Eslint 告诉我需要将props.updateFilter 添加到依赖数组中,虽然我可以忽略这一点,但我觉得这是错误的。"为什么你觉得这是不对的?它是一个传递的道具,消费组件可以对其参考稳定性做出零断言。正如 Diesel 正确指出的那样,您可以记住父级传递给子级的回调。
  • 因为我读过的所有内容都表明这不是一个有效的实例,我应该从依赖数组中排除值。
  • 啊,我在您质疑 linter 时解释了您的评论,并认为 it 是错误的。我明白了。
  • 明白了!不,我的意思是忽略 linter 的行为是错误的。是的,这还不清楚。我的错。

标签: reactjs react-hooks


【解决方案1】:

我该如何解决这个问题?我可以告诉孩子只使用 这个函数的静态版本不知何故?

是的!

所以,如果 props.updateFilter 包含在依赖数组中,那么您就有问题了。您调用该函数,它会导致您的父组件重新渲染。你猜怎么着?父级创建一个新的updateFilter 函数(它做同样的事情,但它创建了一个新函数,对函数的引用是一个新值,所有React 检查)。这会导致子级重新渲染,从而导致您的 useEffect 运行,因为它的依赖项是一个新函数。太糟糕了!

所以...添加useCallback

function updateFilter = useCallback((filterStatus) => {
    ...
    setStateVal(filterStatus);
}, []);

useCallback 一次创建该函数,并且仅在其依赖项发生更改时(应该如此)才创建一个新引用。它有更多的开销,但如果我不确定我会使用它。

另外,奖金,在处理完这些问题后,我使用setState(previousValue =&gt; previousValue + 1) 形式比setState(previousValue + 1) 更多,因为它有很多好处。 previousValue 不必在依赖数组中,多个 setStates 可以在一个渲染周期中堆叠(而不是使用初始值)。

【讨论】:

  • 你是绝对的英雄。像魅力一样工作。我已经阅读了有关 useCallback 以及其他内容的信息,但有点超出了我的想象,所以我错过了它非常适合这种情况。感谢您的帮助。
  • 很高兴它有帮助!我有问题请告诉我。你会读到很多文章说不要过度使用useCallback。我认为成本不会那么高,除非我绝对知道每次都可以创建一个新函数,否则我会使用它。
猜你喜欢
  • 2021-04-15
  • 2022-06-29
  • 2018-06-04
  • 1970-01-01
  • 2018-12-24
  • 2020-12-26
  • 1970-01-01
  • 2023-01-28
  • 2020-02-13
相关资源
最近更新 更多