不要在 render 方法中使用 HOC
React 的 diff 算法(称为协调)使用组件标识来确定它是应该更新现有子树还是将其丢弃并挂载新子树。 如果从 render 返回的组件与前一个渲染中的组件相同(===),则 React 通过将子树与新子树进行区分来递归更新子树。 如果它们不相等,则完全卸载前一个子树。
例子:下面有两个计数器,第一个是正常组件,第二个是函数包裹的高阶组件,点第一个的时候第二个组件的状态会清空。
function WidthWrapper (WrappedComponent) { return class extends React.Component { componentDidMount() { console.log('页面加载完成') } render() { return ( <WrappedComponent /> ); } } } class Example extends React.Component { constructor (props) { super(props); this.state = { number: 0 } } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> </> ) } } class App extends React.Component { constructor (props) { super(props); this.state = { number: 0 } } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { let MyComponent = WidthWrapper(Example) // 在render中创建 return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> <MyComponent /> </> ) } } export default App;
这不仅仅是性能问题 - 重新挂载组件会导致该组件及其所有子组件的状态丢失。
解决上面的问题
function WidthWrapper (WrappedComponent) { return class extends React.Component { componentDidMount() { console.log('页面加载完成') } render() { return ( <WrappedComponent /> ); } } } class Example extends React.Component { constructor (props) { super(props); this.state = { number: 0 } } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> </> ) } } let MyComponent = WidthWrapper(Example) // 在组件之外创建 class App extends React.Component { constructor (props) { super(props); this.state = { number: 0 } } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> <MyComponent /> </> ) } } export default App;
如果 在组件之外创建 HOC,这样一来组件只会创建一次。因此,每次 render 时都会是同一个组件。一般来说,这跟你的预期表现是一致的。
function WidthWrapper (WrappedComponent) { return class extends React.Component { componentDidMount() { console.log('页面加载完成') } render() { return ( <WrappedComponent /> ); } } } class Example extends React.Component { constructor (props) { super(props); this.state = { number: 0 } } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> </> ) } } class App extends React.Component { constructor (props) { super(props); this.state = { number: 0 } this.myComponent = WidthWrapper(Example) // 在构造函数里面创建 } handleClick = () => { this.setState({number: this.state.number + 1}) } render() { let MyComponent = this.myComponent return ( <> <div>{this.state.number}</div> <button onClick={this.handleClick}>+</button> <MyComponent /> </> ) } }
在极少数情况下,你需要动态调用 HOC。你可以在组件的生命周期方法或其构造函数中进行调用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论