【问题标题】:Limit Redux to update only components affected by the change限制 Redux 仅更新受更改影响的组件
【发布时间】: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

标签: reactjs redux flux react-redux


【解决方案1】:

这完全是设计使然。 React 假设你的整个应用程序默认会从上到下重新渲染,或者如果某个组件执行setState 或类似的操作,至少会重新渲染给定的子树。

因为您只连接了应用程序中最顶层的组件,所以从那里开始的所有内容都是 React 的标准行为。父组件重新渲染,导致其所有子组件重新渲染,导致所有它们的子组件重新渲染,以此类推。

在 React 中提高 UI 性能的核心方法是使用 shouldComponentUpdate 生命周期方法来检查传入的 props,如果组件不需要重新渲染,则返回 false。这将导致 React 跳过重新渲染该组件它的所有后代。 shouldComponentUpdate 中的比较通常使用浅引用相等来完成,这就是“相同的对象引用意味着不更新”这件事变得有用的地方。

在使用 Redux 和 connect 时,您几乎总是会发现自己在 UI 中的许多不同组件上使用 connect。这提供了许多好处。组件可以单独提取它们需要的存储状态片段,而不必将它们全部从根组件中传递下来。此外,connect 为您实现了默认的shouldComponentUpdate并且 对您从mapStateToProps 函数返回的值进行类似的检查。因此,从某种意义上说,在多个组件上使用 connect 往往会给您带来性能方面的“免费胜利”。

进一步阅读该主题:

【讨论】:

    【解决方案2】:

    是的,这是设计使然。动作已发送。减速机运行。商店订阅者收到通知“商店已更改”。连接的组件是商店订阅者。

    通常情况下,您不必担心它,直到您可以真正衡量可以归因于此的性能问题 - 不要过早地优化。

    如果您发现它有问题,那么您可以执行以下操作之一:

    • 为你的组件添加一个shouldComponentUpdate 方法,这样他们就可以看到他们收到的道具没有什么不同并且不需要渲染(有很多 Pure Render mixins 和高阶组件可以让这变得简单)
    • 不连接顶级应用,而是直接连接 Navbar 和 Content 组件。应用程序永远不会重新渲染,但如果商店发生变化,孩子们会。并且 react-redux 自动使用 shouldComponentUpdate 仅重新渲染实际上具有新道具的连接组件。

    【讨论】:

    • 我建议再做两件事,使用 Perf 工具来验证优化的需要,并从 React 15.3 开始使用 React.PureComponent(如果适用)
    猜你喜欢
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多