React中的高阶组件(HOC)导致包装组件的额外渲染

时间:2018-07-27 06:13:26

标签: javascript reactjs state react-props higher-order-components

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

下面是App.jsTranslate.jsHOC)。

App.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 ;

Translate.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的{​​{1}}中,然后通过state的机制将其传递给包装的组件。包装的组件接收传递的props并将其保存到props(在state中)。所以我的生命周期是:

componentDidUpdate

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

App.js

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

我会得到

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 来安全地在我的state中使用它们组件。

我错过了什么还是做错了吗?还是App的正常行为? 也许HOC可以解决此问题。

0 个答案:

没有答案