首页 > 解决方案 > React 中的高阶组件 (HOC) 导致包装组件的额外渲染

问题描述

HOC用来包装所有应该有翻译的组件。每个组件都有其动态导入的翻译文件。他们还共享一些共享功能。所以,我创建了HOC,这是一个以组件为参数的函数,返回组件具有一些额外的功能(例如修改componentDidMount)。

下面是App.jsTranslate.js( HOC)。

应用程序.js

import React, { Component } from 'react';
import translated from './Translate';
import './App.css';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      translation: {
        a: '',
      },
      translationRecieved: false
    }
  }
  componentDidMount() {
    console.log('APP mounted')
  }

  componentDidUpdate() {
      console.log('APP did update')
      if(!this.state.translationRecieved) {
         this.setState({
           translation: this.props.translation,
           translationRecieved: true
      })
    }
  }

  render() {
    console.log('APP renders')
    const { t } = this.props
    const { a } = this.state.translation

    return (
        <div className="App">
          <p>This is state: a is {a}</p>
          <hr/>
          <p>Translated `a` is {t(a)}</p>
        </div>
    );
  }
}

const Apptranslated = translated(App);

export default Apptranslated ;

翻译.js

import React from 'react';
import en from './en.json';

const translated  = (WrappedComponent) => {
  class HOC extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            translation: null
        }
    }  

    componentDidMount() {
      console.log('HOC mounted')
      this.setState({
          translation: en
      })  
    }

    componentDidUpdate () {
      console.log('HOC did update')
    }


    translate = (val = '') => `**| ${val} |**`;

    render() {

      console.log('HOC renders')
      return <WrappedComponent 
        translation={this.state.translation} t={this.translate} {...this.props}/>;
    }
  }

  return HOC;
};

export default translated;

我没有在每个组件中定义加载翻译的逻辑,而是使用HOC. HOC将翻译加载到HOC'sstate中,然后通过props. 被包装的组件接收传递props并将其保存到state(in componentDidUpdate)。所以我的生命周期是:

HOC renders
APP renders
APP mounted
HOC mounted
----initial phase ended---
----HOC fetched resources---
HOC renders
APP renders
APP did update
HOC did update
----APP modifies its state---
APP renders
APP did update

如果我对重复代码做同样的事情(在每个组件中定义逻辑)

应用程序.js

import React, { Component } from 'react';
import en from './en.json';
import './App.css';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      translation: {
        a: '',
      },
      translationRecieved: false
    }
  }
  componentDidMount() {
    console.log('APP mounted')
    if(!this.state.translationRecieved) {
      this.setState({
        translation: en,
        translationRecieved: true
      })
    }
  }

  componentDidUpdate() {
      console.log('APP did update')
  }

  translate = (val = '') => `**| ${val} |**`;

  render() {
    console.log('APP renders')
    const { a } = this.state.translation

    return (
        <div className="App">
          <p>This is state: a is {a}</p>
          <hr/>
          <p>Translated `a` is {this.translate(a)}</p>
        </div>
    );
  }
}

export default App;

我会得到

APP renders
APP mounted
APP renders
APP did update

因此,我有额外的渲染,因为我将作为道具的翻译放入组件状态。为什么?因为他们来async。所以我有一个选择:要么在组件中编写一些逻辑来检查翻译是否已经到达,如果没有,则有一些后备选项,或者等到它们来并在我的组件state中安全地使用它们。App

我错过了什么或做错了吗?或者这是正常的行为HOC?也许Redux可以解决这个问题。

标签: javascriptreactjsstatereact-propshigher-order-components

解决方案


推荐阅读