为何修改React中不相关state会导致MenuItems组件意外重渲染?
问题根本原因
- 你将
MenuItems组件直接定义在了App组件内部,这是React开发的典型反模式 - 每当你修改input触发
searchTi状态更新时,App组件会触发重渲染,整个App函数重新执行,此时内部定义的MenuItems函数会生成全新的引用 - React的diff算法在比对组件时,发现前后两次渲染的
MenuItems不是同一个引用,会判定为是全新的组件,因此会先卸载旧的MenuItems,再挂载新的MenuItems,表现出来就是你看到的“重新加载”效果,这一过程和menuitems是否变化没有任何关系
解决方案
- 首先把
MenuItems组件移到App组件外部定义,通过props传递依赖的menuitems参数 - 可以搭配
React.memo包裹MenuItems,只有当传入的props发生变化时才会触发重渲染,进一步优化性能
修改后的参考代码:
import React, {useState, useEffect, memo} from 'react' // 移到App外部定义,用memo包裹做浅比较优化 const MenuItems = memo(({menuitems}) => { const renderMenuItems = () => { if (menuitems && menuitems.length){ console.log("Render") return menuitems.map((name) => { return ( <button key={name}>{name}</button> ) }) } } return renderMenuItems() }) function App() { const [menuitems, setMenuitems] = useState(null) useEffect(() => { console.log("Init") setMenuitems(["menu1","menu2","menu3"]) },[]) const [searchTi, setSearchTic] = useState('') return ( <div className="App"> {menuitems && <MenuItems menuitems={menuitems}/>} <p>Value: {searchTi}</p> <input value={searchTi} onChange={(e) => setSearchTic(e.target.value)}/> </div> ); } export default App;
修改后输入内容触发App重渲染时,MenuItems的引用没有变化,且传入的menuitems props也没有发生变化,memo会跳过重渲染,不会再出现反复重新加载的问题。
内容的提问来源于stack exchange,提问作者Dvashington
相关产品推荐
相关产品推荐

