我知道您可以通过将数组作为可选的第二个参数传递来告诉React跳过效果。
例如:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
但是,如果我想控制比较怎么办?添加我自己的比较逻辑。
我希望像React.memo
这样的东西可以将函数作为第二个参数传递。
答案 0 :(得分:16)
添加到PAT-O-MATION的答案中,
React.memo还接受第二个参数,该参数可用于确定组件是否
应该呈现还是不呈现。
如果函数返回true,则组件将不会在更改该prop时重新渲染,相反,当返回值为false时,组件将更新
function SomeComp({prop1, prop2}) {
return(
..
)
}
React.memo(SomeComp, (props, nextProps)=> {
if(props.prop1 === nextProps.prop1) {
// don't re-render/update
return true
}
})
注意:只有在回调函数返回false时,组件才会重新呈现,因此在上述情况下,即使prop2值更改,它也不会重新呈现
答案 1 :(得分:3)
在 Gabriele Petrioli 上方的评论中,链接到React.memo文档,该文档解释了如何实现shouldComponentUpdate。我正在搜索shouldComponentUpdate + useEffect +“ react hooks”的组合,结果出现了。因此,在解决了链接文档中的问题之后,我想我也将信息带到这里。
这是实现shouldComponentUpdate的旧方法:
class MyComponent extends React.Component{
shouldComponentUpdate(nextProps, nextState){
return nextProps.value !== this.props.value;
}
render(){
return (
<div>{"My Component " + this.props.value}</div>
);
}
}
新的React Hooks方式:
React.memo(function MyComponent (props) {
return <div>{ "My Component " + props.value }</div>
})
我知道您可能在问题中提出了更多的要求,但是对于任何来自google的人来说,他们都知道如何实现shouldComponentUpdate。
答案 2 :(得分:2)
另一种选择是使用useRef来保存数据,而仅使用useState来存储要显示的数据。 有时这比备忘录方法更好:最近我遇到一个案例,其中React在使用React.memo时仍然不必要地渲染,并且弄乱了一些PIXI的显示。 下面的方法为我解决了这个问题...希望我没有做反模式:-)
const countRef = useRef(0);
const [countDisplay, setCountDisplay] = useState(0);
yourUpdateFunction = () => {
// This is where count gets updated
countRef.current = countRef.current + 1;
if ((countRef.current % 2) === 0) setCountDisplay(countRef.current);
}
return (<p>countDisplay</p>);
答案 3 :(得分:0)
如果在数组中传递的属性发生更改,则传递可选的第二个数组参数会启动effect函数-就像在将prop传递给组件时,类组件中的shouldComponentUpdate
方法将运行。您可以根据参数的值决定效果功能-是否要应用效果。
答案 4 :(得分:0)
这是一个自定义钩子,它接受一个updater函数,并返回一个仅在updater函数返回true时才更改的值,该值可以在第二个参数中传递给useEffect
或useCallback
或{ {1}}强制重新渲染:
useMemo
例如,这只会在计数为偶数时更新文档标题:
function useShouldRecalculate(shouldRecalculateFn) {
const prevValueRef = useRef(0);
if(shouldRecalculateFn()) {
// If we need to recalculate, change the value we return
prevValueRef.current += 1;
} // else we return the same value as the previous render, which won't trigger a recalculation
return prevValueRef.current;
}
在大多数情况下,我不建议您这样做。
通常,将使用惯用的钩子API来完成同一任务的方法更加简洁。 (以上示例可能只是在更新文档标题的行周围放置了const shouldUpdateTitle = useShouldRecalculate(
() => count % 2 === 0
);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [shouldUpdateTitle]); // eslint-disable-line react-hooks/exhaustive-deps
块。)
也许更重要的是,if
参数不仅涉及优化,而且还涉及保持闭包值是最新的,并避免出现诸如以下的错误:
deps
const [count, setCount] = useState(0)
const increment = useCallback(() => {
// Bug: `count` is always 0 here, due to incorrect use of the `deps` argument
setCount(count + 1)
}, [])
linter规则将捕获此错误,但是您必须在使用自定义逻辑来控制执行的任何位置禁用该规则。
使用自定义的备忘逻辑可能会使您的组件更容易出现错误,并且通常很难进行推理。因此,我认为这react-hooks/exhaustive-deps
钩了不得已的办法。
答案 5 :(得分:0)
除了 Avinash的答案。 返回值的重要说明:
shouldComponentUpdate() {
// returns true by default
// return false if you don't need re-render
}
export default React.memo(Component, (props, nextProps) => {
if(props.prop1 === nextProps.prop1) {
// return true if you don't need re-render
}
})