React Redux和Should组件更新优化



代码:

根成分

    <Provider store={Store}>
       <AppLayoutContainer>
           {this.props.template}
       </AppLayoutContainer>
    </Provider>

应用程序布局容器

....some code
  return(
    <div className={`AppLayoutContainer`}>
       <Modal isOpen={isModalShown} .... />
       <div>{children}</div>
     </div>
  )
....some code
function mapStateToProps(state) {
  const { app } = state;
  return {
    isModalShown: app.isModalShown
   }
}
export default connect(mapStateToProps)(AppLayoutContainer);

问题:

每次Applayoutcontainer从Redux获得isModalShown时,我的整个应用程序都在重新渲染,这非常糟糕。我只需要重新渲染Modal组件,不要触摸我的children。我认为ShouldComponentUpdate方法是可能的,但我真的不知道怎么做

有什么想法吗?我知道有人在他的项目中做到了这一点,并可以为此提供一些最佳实践建议。感谢


更新:

阅读所有答案,是的,将Modal与Store连接是一个很好的解决方案,但是如果

1( 我希望Modal组件是纯的(可重复使用(,像还是组件?

2( 我需要在AppLayoutContainer中使用isModalShown吗?

return(
    <div className={`AppLayoutContainer`}>
       <Modal isOpen={isModalShown} .... />
       <div>{children}</div>
     </div>
  )

更新2.0

谢谢你的回答,但我能用这个做什么

主要的问题是,当我显示Modal组件时,我需要模糊我的所有内容,因为我知道blur()只能应用于要工作的内容(而不是覆盖我的内容的绝对位置div(,并且像这个一样

return(
        <div className={`AppLayoutContainer`}>
           <Modal isOpen={isModalShown} .... />
           <div className={isModalShown ? 'blured' : null }>{children}</div>
         </div>
      )

但每次我显示Modal时,我的整个应用程序都会重新渲染,我需要冻结它。在这里为child构建容器并执行shouldcomponentupdate的解决方案不好,React如何比较whole组件??它只比较道具中不可变的字段。

有什么解决方案吗?

您应该做的不是传递AppLayoutContainermapStateToProps函数中的isModal,而是传递connect Modal本身。

mapStateToProps的任何更改结果都将导致connect ed组件重新发送。在您的情况下,mapStateToProps connectAppLayoutContainer返回isModalShown的值,这将导致AppLayoutContainer重新发送。

如果你只想重新发送Modal本身,那么只需要

export default connect(state => ({isOpen: state.app.isModalShown}))(Modal)

在你的Modal文件中,或者如果你更喜欢的话,放在一个单独的文件中。

另外,从AppLayoutContainer中删除isModalShown道具,因为您不需要它因为将其保留在那里意味着每次isModalShown更改时,AppLayoutContainer仍将重新发送(这正是您试图修复的(。

更新关于问题更新:

问题1:

你可以有一个纯Modal

export default function Modal(props) {
  return <span>Open={props.isOpen}</span>;
}

然后,您可以为特定用途制作特定的模式:

import Modal from './modal';
import { connect } from 'react-redux';
export default const AppLayoutModal = connect(state => ({isOpen: state.app.isModalShown}))(Modal);

你可以对各种不同的模态多次这样做。事实上,这就是为什么使用纯组件是个好主意。

问题2:

如果你想在AppLayoutContainer中使用isModalShown,那么你有一些选择:

  • 只要使用它。React总是渲染整个组件。因为这只是一种渲染方法。它会更新DOM(如果有的话(,使其更细粒度,但如果您希望在某个东西发生变化时渲染更少的东西,那么就由您来缩小渲染函数。如果你把组件放大,那么整个组件就会重新出现
  • 您可以将组件分解为更小的组件,以便分别渲染它们。您可以通过connect直接使一个小组件只使用isModalShown,这样大的AppLayoutContainer就不会改变。子零部件可以并且确实独立于其父零部件进行更新

更新2

要模糊整个应用程序,只需在应用程序中添加一个类即可。子组件将不会重新应答。Redux阻止子级渲染,因为它注意到子级没有使用isModalShown。生成的React元素与上一次渲染的对象(引用(完全相同。React看到它是同一个元素,并知道不要更新整个树。这是因为React元素是不可变的。你的整个应用程序不会重新发送。事实上,React只会在class属性中添加或删除class。

如果您的子级不使用Redux来阻止渲染在树上进行,则可以将子级封装在Redux连接的组件中。或者,也可以使用shouldComponentUpdate来防止渲染子对象。

Bare React要求您从根向树下发送数据。Redux要求您在需要数据的地方将数据注入树中。后者的好处是不需要重新考虑其他因素。如果没有Redux,除了组件使用shouldComponentUpdate停止传播外,每次更改都会重新绘制整个树。但是,这不仅会停止当前组件的渲染,还会停止所有子组件的渲染。Redux消除了这一点,因为子组件可以在没有父组件合作或知情的情况下更新其道具。

简而言之:在任何地方使用Redux都可以提高速度。

这里可能有不同的策略。

  1. 在您的子组件中使用shouldComponentUpdate(在这种情况下非常混乱和不雅(
  2. 将Modal组件连接到商店,而不是AppLayoutContainer
  3. isModalShown存储在Modal的状态,而不是全局状态

在可能的情况下,最后的解决方案通常是更合适的IMHO。您将UI状态保留在相关组件中,因为您不需要经常在其他组件中意识到这一点。

class Modal extends Component {
  state = {
    isModalShown: false,
  };
  render() {
    // ...
  }
}

如果您需要在其他地方了解isModalShown,则应连接Modal组件,而不是AppLayoutContainer

export default connect((state) => ({
  isModalShown: state.app.isModalShown,
}))(Modal)

我认为DDS和Anthony Dugois有权这样做,但如果这些不是你想要的答案,你可以总是将children管道传输到一个新组件中,并在那里使用shouldComponentUpdate

相关内容

  • 没有找到相关文章

最新更新