React Context API 很慢
Posted
技术标签:
【中文标题】React Context API 很慢【英文标题】:React Context API is slow 【发布时间】:2019-06-07 21:55:56 【问题描述】:我正在试验新的 Context API 和钩子。我创建了一个带有侧边栏(树视图)、页脚和主要内容页面的应用程序。我有一个上下文提供者
const ContextProvider: FunctionComponent = (props) =>
const [selected, setSelected] = useState(undefined);
const [treeNodes, setTreeNodes] = useState([]);
return (
<MyContext.Provider
value=
actions:
setSelected,
setTreeNodes
,
selected,
treeNodes
>
props.children
</MyContext.Provider>
);
作为我的内容组件,我有一个包含大约 1000 个项目的 DetailsList(Office Fabric UI)。当我单击列表中的项目时,我想在上下文中更新所选项目。这有效,但它真的很慢。选择列表中的项目大约需要 0,5-1 秒。该列表是虚拟化的。我已经在生产版本中尝试过。事情要好一些,但点击列表时有明显的滞后。 Footer 正在使用 myContext 来显示有关所选项目的信息。
这是我的组件中的一些代码
const cntx = useContext(MyContext);
const onClick = (item) =>
cntx.actions.setSelected(item);
;
我是否使用了错误的上下文?
我创建了一个示例沙箱来演示。您可以滚动到大约第 100 个索引并单击几次以查看它是如何变得无响应的。
https://codesandbox.io/s/0m4nqxp4m0
这是 Fabric DetailsList 的问题吗?它会重新渲染多次吗?我相信问题出在“复杂”的 DatePicker 组件上,但我不明白为什么会重新渲染 DetailsList?它没有在渲染函数中使用任何上下文属性。我希望只有 Footer 组件在每次上下文更改时重新呈现
【问题讨论】:
控制台中有很多"The icon "calendar" was used but not registered. See http://aka.ms/fabric-icon-usage for more information. "
警告 - 我担心仅此日志记录会导致问题 - 请检查 :) #edit - codesandbox.io/embed/llj1zk19rz
【参考方案1】:
使用 useMemo 记住您选择的项目,以避免在引用同一项目时创建新对象。然后在专用上下文中传递它
【讨论】:
【参考方案2】:在您的解决方案中,每当您的组件被重新渲染时,value
的新实例将作为道具传递下来。这也会触发子元素的重新渲染。
如果您使用钩子,为了防止这种情况,请记住您要传递的 value
对象,在 useMemo
或 useCallback
钩子中。事实上,这应该作为基本的 React 实践应用于任何组件,而不仅仅是上下文组件。除非您传递原始值(字符串、数字、...),否则不要直接创建实例或内联函数并将其作为道具传递。确保你传递的 props 在 React 组件的每个渲染周期后都不会改变。
【讨论】:
【参考方案3】:注意事项 因为上下文使用引用标识来确定何时重新渲染,所以当提供者的父级重新渲染时,有一些陷阱可能会触发消费者的无意渲染。例如,下面的代码将在每次 Provider 重新渲染时重新渲染所有消费者,因为总是为 value 创建一个新对象:
class App extends React.Component
render()
return (
<Provider value=something: 'something'>
<Toolbar />
</Provider>
);
To get around this, lift the value into the parent’s state:
class App extends React.Component
constructor(props)
super(props);
this.state =
value: something: 'something',
;
render()
return (
<Provider value=this.state.value>
<Toolbar />
</Provider>
);
https://reactjs.org/docs/context.html#caveats
【讨论】:
以上是关于React Context API 很慢的主要内容,如果未能解决你的问题,请参考以下文章
在 react-native@0.55 发布版本中获取 API 很慢
如何创建使用 Typescript 传递函数的 React Context
React开发(206):react代码分割之context的api
React - 新的 Context API 不适用于 Class.contextType,但适用于 Context.Consumer