在我的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 回答
在您发布的代码中,我认为您提到的功能都会改变
this.parentSize
然后重新呈现页面 . 如果this.parentSize
的值没有改变,则重新分配其值:如果我的理解是正确的,那么子组件必须重新渲染,因为用于生成组件的信息已经改变,因此必须重新渲染组件以考虑道具更改 . 很可能是DOM没有变化,因此页面不会在视觉上发生变化 .
您可以使用Perf add on并使用
printOperations
函数来检查正在执行的操作 .防止重新渲染的一种方法是使用
shouldcomponentupdate
并在不希望重新渲染组件时返回false编辑:
基于上面提供的信息,您似乎想通过调用父组件上的函数来更新子组件,但是不希望父组件重新呈现?
如果是这种情况,您可以通过执行以下操作来执行此操作:
子组件第一次呈现时,您调用
componentWillMount
,并获得您希望能够从父级控制的道具,并将其保存为状态,如下所示:然后在这个组件中你创建一个名为的函数:
从那时起,这个变量由
state
控制而不是props
接下来,在父页面上,组件需要具有
ref
变量,如下所示:现在,您可以通过执行以下操作从父页面调用
updateMyProp
函数:这将导致子组件呈现,而不是父组件
我希望我能正确理解你的问题!!
我已经确认该问题与我最近的React-Router 4.x升级有关 . React-Router的文档:
当您使用组件(而不是下面的render或children)时,路由器使用React.createElement从给定组件创建新的React元素 . 这意味着如果为组件属性提供内联函数,则每次渲染都会创建一个新组件 . 这导致现有组件卸载和新组件安装,而不是仅更新现有组件 . 使用内联函数进行内联渲染时,请使用render或children prop(下面) .
感谢大家的支持 .