限制 Redux 仅更新受更改影响的组件
Posted
技术标签:
【中文标题】限制 Redux 仅更新受更改影响的组件【英文标题】:Limit Redux to update only components affected by the change 【发布时间】:2016-12-15 22:58:12 【问题描述】:试图理解 React-Redux,我发现当状态的任何部分发生变化时,我的所有组件都会获得新的 props,这很不寻常。那么这是设计使然还是我做错了什么?
示例应用
class App extends React.Component
render()return (
<div>
<Navbar data=this.props.navbar />
<Content data=this.props.content />
</div>);
select (state) => ( navbar:state.navbar, content:state.content);
export default connect(select)(App);
组件
export const NavbarForm = props =>
console.log('RENDERING with props--->',props);
return (<h1>NAV props.data.val</h1>);
;
export const ContentForm = props =>
console.log('RENDERING CONTENT with props--->',props);
return (<h1>CONTENT props.data.val</h1>);
;
////////INDEX.js//////
const placeholderReducer = (state=val:0,action)=>
//will update val to current time if action start with test/;
if(action.type.indexOf('TEST/') === 0)return val:Date.now();
return state;
export const rootReducer = combineReducers(
navbar:placeholderReducer,
content: (state,action)=>(state || ), //**this will never do a thing.. so content should never updates right !!**
);
const store = createStore(rootReducer, , applyMiddleware(thunk));
render( <Provider store=store> <App /></Provider>, document.getElementById('app')
);
setInterval(()=> store.dispatch(()=>type:'TEST/BOOM') ,3000);
好的,在这个应用程序中,我期望导航栏组件将每 3000 毫秒更新一次,而内容组件将永远不会更新,因为它的减速器将始终返回相同的状态。
但我发现每次触发动作时两个组件都会重新渲染,这真的很奇怪。
这是设计使然吗?如果我的应用有 100 多个组件,我应该担心性能吗?
【问题讨论】:
您的应用在性能方面无法很好地扩展,但我会回答您的主要问题。将您的导航栏功能组件转换为基于类的组件并添加生命周期方法componentWillReceiveProps(nextProps)
然后设置您的状态...要了解更多信息,请阅读here
@AdegbuyiAdemola 为什么它不会扩展?这不是 redux 文档中提出的结构吗?你能详细说明:)吗?添加生命周期将如何阻止 react-redux 更新道具?
如果存储出现问题,您可能会遇到最大堆栈超出错误。我没有说添加生命周期会阻止 react-redux ......我的意思是,你也应该在 Navbar 上使用它并使 Navbar 成为基于类的组件
请记住,在 React 中 render
并不一定意味着更改 DOM。这意味着运行渲染算法来检查 DOM 是否需要更新。所以render
操作可能是亚毫秒级的。另外,请查看新的React.PureComponent
【参考方案1】:
这完全是设计使然。 React 假设你的整个应用程序默认会从上到下重新渲染,或者如果某个组件执行setState
或类似的操作,至少会重新渲染给定的子树。
因为您只连接了应用程序中最顶层的组件,所以从那里开始的所有内容都是 React 的标准行为。父组件重新渲染,导致其所有子组件重新渲染,导致所有它们的子组件重新渲染,以此类推。
在 React 中提高 UI 性能的核心方法是使用 shouldComponentUpdate
生命周期方法来检查传入的 props,如果组件不需要重新渲染,则返回 false
。这将导致 React 跳过重新渲染该组件和它的所有后代。 shouldComponentUpdate
中的比较通常使用浅引用相等来完成,这就是“相同的对象引用意味着不更新”这件事变得有用的地方。
在使用 Redux 和 connect
时,您几乎总是会发现自己在 UI 中的许多不同组件上使用 connect
。这提供了许多好处。组件可以单独提取它们需要的存储状态片段,而不必将它们全部从根组件中传递下来。此外,connect
为您实现了默认的shouldComponentUpdate
,并且 对您从mapStateToProps
函数返回的值进行类似的检查。因此,从某种意义上说,在多个组件上使用 connect
往往会给您带来性能方面的“免费胜利”。
进一步阅读该主题:
Redux FAQ: Connecting multiple components React/Redux Links: Performance articles【讨论】:
【参考方案2】:是的,这是设计使然。动作已发送。减速机运行。商店订阅者收到通知“商店已更改”。连接的组件是商店订阅者。
通常情况下,您不必担心它,直到您可以真正衡量可以归因于此的性能问题 - 不要过早地优化。
如果您发现它是有问题,那么您可以执行以下操作之一:
为你的组件添加一个shouldComponentUpdate
方法,这样他们就可以看到他们收到的道具没有什么不同并且不需要渲染(有很多 Pure Render mixins 和高阶组件可以让这变得简单)
不连接***应用,而是直接连接 Navbar 和 Content 组件。应用程序永远不会重新渲染,但如果商店发生变化,孩子们会。并且 react-redux 自动使用 shouldComponentUpdate
仅重新渲染实际上具有新道具的连接组件。
【讨论】:
我建议再做两件事,使用Perf
工具来验证优化的需要,并从 React 15.3 开始使用 React.PureComponent(如果适用)以上是关于限制 Redux 仅更新受更改影响的组件的主要内容,如果未能解决你的问题,请参考以下文章