首页 文章

React JSX:重新渲染父组件重新装入子组件是否正常?

提问于
浏览
0

在我的React App的根组件中,我有这个:

class App extends Component {
...
  ComponentDidMount() {
    window.addEventListener('resize', this.handleResize, false);
  }
  handleResize{
    this.parentSize = {height: window.innerWidht - this.node.offsetLeft ..., width: ...};
    this.forceUpdate();
  }
  render() {
    <div ref="e=>this.node=e}>
      <ChildComponent parentSize={this.ParentSize} />
    </div>
  }
}

我注意到当App组件通过setState或forceUpdate()重新渲染时,子组件实际上已重新装入(因此每次更新时都会调用componentWillUnmount,componentWillMount,componentDidMount) . 我期望的行为是只再次调用Child组件的render函数 . 我最近升级到React-router 4.x,所以我不确定它是否与此相关 .

有人可以告诉我这是否是设计的?让我的componentDidMount多次调用会导致一些问题,因为我尝试在其中获取数据,并且我不希望在调整大小期间多次执行那么昂贵的操作 .

更新:

我发现了这个问题的可能原因 . 我有多个嵌套组件,因为很难发布整个项目,有时很难发布导致问题的实际代码 . 但我认为就是这样:

return (
  <div className="app-view" style={style} ref={el=>this.node=el}>
    <Switch>
      <Route exact path='/' component={() => <Home store={store} />} />
      <Route path='*' component={Error404} />
    </Switch>
  </div>
);

在这里,我试图将道具传递给路线中的组件(React-router 4.x)我这样做是通过提供创建主页的功能,这可能是在每次渲染时重新创建主页 .

那么问题就变成了,如何在路径中的每个渲染中传递道具而不重新创建页面?

2 回答

  • 0

    在您发布的代码中,我认为您提到的功能都会改变 this.parentSize 然后重新呈现页面 . 如果 this.parentSize 的值没有改变,则重新分配其值:

    this.parentSize = {height: window.innerWidht - this.node.offsetLeft ..., width: ...};
    

    如果我的理解是正确的,那么子组件必须重新渲染,因为用于生成组件的信息已经改变,因此必须重新渲染组件以考虑道具更改 . 很可能是DOM没有变化,因此页面不会在视觉上发生变化 .

    您可以使用Perf add on并使用 printOperations 函数来检查正在执行的操作 .

    防止重新渲染的一种方法是使用 shouldcomponentupdate 并在不希望重新渲染组件时返回false

    编辑:

    基于上面提供的信息,您似乎想通过调用父组件上的函数来更新子组件,但是不希望父组件重新呈现?

    如果是这种情况,您可以通过执行以下操作来执行此操作:

    子组件第一次呈现时,您调用 componentWillMount ,并获得您希望能够从父级控制的道具,并将其保存为状态,如下所示:

    componentWillMount() {
      const { myProp } = this.props;
      this.setState({
        myProp
      });
    }
    

    然后在这个组件中你创建一个名为的函数:

    updateMyProp(newProp) {
      this.setState({
        myProp: newProp
      })
    }
    

    从那时起,这个变量由 state 控制而不是 props

    接下来,在父页面上,组件需要具有 ref 变量,如下所示:

    <Yourcomponent
      ref={d=> this.componentName = d}
      ...
    />
    

    现在,您可以通过执行以下操作从父页面调用 updateMyProp 函数:

    this.componentName.updateMyProp(someNewValue)
    

    这将导致子组件呈现,而不是父组件

    我希望我能正确理解你的问题!!

  • 3

    我已经确认该问题与我最近的React-Router 4.x升级有关 . React-Router的文档:

    当您使用组件(而不是下面的render或children)时,路由器使用React.createElement从给定组件创建新的React元素 . 这意味着如果为组件属性提供内联函数,则每次渲染都会创建一个新组件 . 这导致现有组件卸载和新组件安装,而不是仅更新现有组件 . 使用内联函数进行内联渲染时,请使用render或children prop(下面) .

    感谢大家的支持 .

相关问题