React 的 useEffect 中更高级的比较
Posted
技术标签:
【中文标题】React 的 useEffect 中更高级的比较【英文标题】:More advanced comparison in React's useEffect 【发布时间】:2020-01-23 15:37:27 【问题描述】:我正在寻找一种方法来执行更高级的比较,而不是 useEffect
React 挂钩的第二个参数。
具体来说,我正在寻找更像这样的东西:
useEffect(
() => doSomething(),
[myInstance],
(prev, curr) => /* compare prev[0].value with curr[0].value */
);
请问我从 React 文档中遗漏了什么,或者有什么方法可以在已经存在的基础上实现这样的钩子吗?
如果有办法实现它,它会这样工作:第二个参数是一个依赖数组,就像来自 React 的 useEffect
钩子,第三个是带有两个参数的回调:依赖数组上一次渲染,以及依赖数组当前渲染。
【问题讨论】:
你可以使用 React.memo 函数 【参考方案1】:你可以使用 React.memo 函数:
const areEqual = (prevProps, nextProps) =>
return (prevProps.title === nextProps.title)
;
export default React.memo(Component, areEqual);
或为此使用自定义钩子:
How to compare oldValues and newValues on React Hooks useEffect?
【讨论】:
【参考方案2】:在class based components
中很容易执行deep comparison
。 componentDidUpdate
提供previous props
和previous state
中的snapshot
componentDidUpdate(prevProps, prevState, snapshot)
if(prevProps.foo !== props.foo) /* ... */
问题是useEffect
它与componentDidUpdate
不完全一样。考虑以下
useEffect(() =>
/* action() */
,[props])
当action()
被调用时,您唯一可以断言当前props
是它已更改(浅比较断言为false
)。您不能拥有prevProps
的快照,因为hooks
就像常规函数一样,没有确保同步性(和注入参数)的生命周期的一部分(并且没有实例)。实际上,唯一能确保 hooks 值完整性的是order of execution。
usePrevious
的替代方案
更新前检查值是否相等
const Component = props =>
const [foo, setFoo] = useState('bar')
const updateFoo = val => foo === val ? null : setFoo(val)
当您需要确保effect
仅运行一次(在您的用例中无用)时,这在某些情况下很有用。
useMemo
:
如果您想执行比较以防止不必要的render
调用(shoudComponentUpdate
),那么useMemo
是要走的路
export React.useMemo(Component, (prev, next) => true)
但是当您需要在已经运行的效果中访问 previous
值时,没有其他选择了。因为如果您已经在 useEffect
内部,则意味着 dependency
它已经更新(当前渲染)。
为什么usePrevious
有效
useRef
不仅适用于 refs
,它是一种非常直接的方式来获取 mutate
值,而不会触发重新渲染。所以循环如下
Component
被挂载
usePrevious
将初始值存储在 current
中
props
更改触发内部重新渲染 Component
useEffect
被调用
usePrevious
被调用
注意usePrevious
总是在useEffect
之后调用(记住,顺序很重要!)。因此,每次您在 useEffect
内时,current
的值 useRef
总是会落后一个渲染。
const usePrevious = value =>
const ref = useRef()
useEffect(() => ref.current = value,[value])
const Component = props =>
const A = props
useEffect(() =>
console.log('runs first')
,[A])
//updates after the effect to store the current value (which will be the previous on next render
const previous = usePrevious(props)
【讨论】:
我无法弄清楚这是如何工作的。如果依赖项是一个属性,这似乎不起作用 这适用于A
和 B
的 props、state 或任何其他值
很抱歉打扰您了,您能详细解释一下吗?我在 React 文档站点上读到了这个自定义钩子,但不能说我 100% 理解它。是否与分发效果的方式有关?谢谢!
我会给出我的答案以上是关于React 的 useEffect 中更高级的比较的主要内容,如果未能解决你的问题,请参考以下文章
如何比较 React Hooks useEffect 上的 oldValues 和 newValues?多次重新渲染
[react] useEffect和useLayoutEffect有什么区别?