发布于:2021-02-04 11:15:20
0
171
0
在许多情况下,React组件将在不必重新渲染时重新渲染。
如果渲染的结果与组件上一次渲染的结果完全相同,则最好完全跳过该渲染(协调)步骤。
基于类的组件
shouldComponentUpdate
在类组件中,方法shouldComponentUpdate
允许这样做。
它是在render()
之前调用的生命周期方法。该方法返回一个布尔值。如果render()
可以跳过,这个布尔值告诉React。
当true
时,render()
将像平常一样执行。
当false
时,告诉React它可以跳过执行render()
。
用下一个道具和下一个状态调用 默认情况下, 完全不指定此方法。 shouldComponentUpdate(nextProps, nextState) { 不要依赖于此来完全阻止渲染。它现在可能工作,但它可能会导致错误,并可能在未来发生变化。相反,将其视为一个反应提示,告诉它“您可以安全地跳过渲染,结果将与上一个结果相同”。 在您知道之前,该方法看起来会是这样的。 shouldComponentUpdate(nextProps, nextState) { 我只是想看看有没有什么道具或者状态改变了,为什么这么难? 这会减少跳过必要更新的可能性(例如,添加新道具时)。 除非您确信需要自定义道具,否则最好选择 这意味着这两个片段是等价的。 class Driver extends React.Component { 当试图将同样的优化应用于函数组件而不是基于类的组件时,问题就出现了。函数组件不能真正跳过渲染步骤。函数组件(实际上只是一个函数)要么执行要么不执行 这就是备忘录有帮助的地方。 备忘录基本上是一种技术,用于以后记住一些东西。 React不能只记住数据片段,它可以记住整个组件。 前两个示例是针对基于类的组件的, 不像在基于类的组件中那样跳过渲染步骤, // the function component 带有道具的记忆驱动程序组件的初始呈现 函数组件render <p>Charles Leclerc</p>。 道具更改为 组件渲染 <p>Daniel Ricciardo</p> 触发驱动程序更新的其他更改组件 React使用前面的结果而不是计算渲染结果:<p>Daniel Ricciardo</p> 默认情况下, 比较函数还返回一个布尔值。 该布尔值告诉React它是否应该使用组件的前一个结果,而不是计算新的结果。 当 当 小心!这与 使用上一个道具和下一个道具调用比较函数。这允许复杂的逻辑,将当前道具与以前的道具进行比较,以确定输出是否不同,因此应使用组件的记忆结果/备忘录。 // the function component 要使用基于类的组件扩展并行程序: 除非您确信需要自定义比较函数,否则最好使用默认行为。 示例 在这个演示中,有一个顶级组件有两个状态,一个是 您可以通过按钮增加 顶部组件有4个子组件,所有子组件都将显示 只有在更新 而 const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]); 告诉 传递的函数中使用的每个值都应包含在依赖项数组中。 这将防止许多意外行为。 React团队创建了一个ESLint包, 示例 import React from 'react'; 使用props的驱动程序组件的初始呈现 函数组件计算 props更改为 React.useMemo看不到依赖项数组中的任何内容已更改,并且不会重新计算numOfPodiums 使用 道具再次更改为 React.useMemo 看到依赖项数组中发生了一些变化并计算 numOfPodiums 并使用新计算的值。 这是特定 但值完全可以是函数! 这意味着这两个片段是等价。 const memoizedFunction = React.useMemo(function() { 这将记忆第一个参数(函数)返回的值,该值是一个名为 const memoizedFunction = React.useCallback(function doTheThing(a, b) { 这将记忆第一个参数,这是一个名为 与 函数shouldComponentUpdate()
。这允许复杂的逻辑,将当前的属性/状态与以前的属性/状态进行比较,以确定输出是否不同,因此组件应该更新。shouldComponentUpdate()
返回true。
return true
}shouldComponentUpdate
中的逻辑很快就会变得非常复杂,并且容易出错。
const propsComparison = this.props.a !== nextProps.a && this.props.b !== nextProps.b && this.props.c !== nextProps.c && this.props.d !== nextProps.d
const stateComparison = this.state.one !== nextState.one && this.state.two !== nextState.two && this.state.three !== nextState.three
return propsComparison && stateComparison
}React.PureComponent
React.PureComponent
就是这样!PureComponent
执行道具和状态的浅表比较(通过使用Object.is)。PureComponent
。
shouldComponentUpdate() {
// a shallow comparison of all the props and state
}
render() {{this.props.name};
}
}class Driver extends React.PureComponent { render() {{this.props.name}; } }
功能部件
React.memo
React.memo
这样做!React.memo
是针对函数组件的。React.memo
将重用上次渲染的结果,而不是计算新结果。
const Driver = function(props) {
return{props.name};
};
// exporting the memoized function component
export default React.memo(Driver);{ name: "Charles Leclerc" }
{ name: "Daniel Ricciardo" }
React.memo
看到道具没有更改。React.memo
与React.PureComponent
相当,因为它对所有道具进行了浅层比较(使用对象.is如果您想获得更多的控制权并负责比较,React.memo
接受第二个参数,即比较函数。这使得它在基于类的组件中与shouldComponentUpdate
相当。false
时,函数组件将像平常一样执行。true
时,函数组件将不执行,并且将使用前面的结果。shouldComponentUpdate
相反!
const Driver = function(props) {
return{props.name};
};
// the custom comparison function
const comparisonFn = function(prevProps, nextProps) {
return prevProps.name === nextProps.name;
};
// exporting the memoized function component
export default React.memo(Driver, comparisonFn);count
和一个是unusedCount
。顾名思义,它仍将被闲置。count
和unusedCount。
count
以及该子组件渲染的次数。count
时,具有上述优化之一的组件才会渲染。当更新unusedCount
时,其他的也会渲染。React.memo
与React.useMemo
React.memo
是一个高阶组件,因为它接受一个组件并返回新的/记忆的组件。React.useMemo
是一个hook(它是一个函数)。它接受一个函数并返回所传递函数的记忆返回值。React.useMemo
React.useMemo
接受函数作为第一个参数。此函数返回的值是React.useMemo
将返回的值。只有在必要时才会重新计算。React.useMemo
将返回已记忆/已记忆的值(如果没有)。React.useMemo
是否应该通过第二个参数(数组)重新计算结果。传递的函数返回的值只有在依赖项数组中的某些内容发生更改时才会再次计算。不传递任何内容将导致每次呈现组件时都计算该值(并导致函数运行)。eslint-plugin-react-hooks
,用于在违反hook规则时发出警告。正在完成的依赖关系数组由该包中名为exhaustive-deps
的规则检查。
function calculatePodiums(name) {
// very expensive calculation
return numResult;
}
const Driver = function(props) {
const numOfPodiums = React.useMemo(() => calculatePodiums(props.name), [
props.name
]);
return (My name is: {props.name}I drive for: {props.team}I have been on the podium {numOfPodiums} times);
};{ name: "Kimi Räikkönen", team: "Ferrari" }
numOfPodiums
并使用该计算的结果进行呈现。{ name: "Kimi Räikkönen", team: "Alfa Romeo Racing" }
numOfPodiums
的memo/membered值。{ name: "Antonio Giovinazzi", team: "Alfa Romeo Racing" }
React.useCallback
React.useMemo
用法的快捷方式。React.useMemo
返回已记忆的值.React.useCallback
返回已记忆的函数.
return function doTheThing(a, b) {
// do the thing
}
}
}, [a, b])doTheThing。
// do the thing
}
}, [a, b])doTheThing
的函数。React.useMemo
一样,第二个参数是一个依赖项数组。React.useCallback
仅当该数组中的某些内容发生更改时才会返回更改。
作者介绍