React - 'Do not use HOC’s in the render method of a component. Access the HOC outside the component definition.' 是什么意思?

React - What is meant by 'Do not use HOC’s in the render method of a component. Access the HOC outside the component definition.'?

我正在学习 HOC 并一直在阅读上面的引用,但我不明白它的意思。如果我的 HOC 向我的消费组件添加了一个方法,我可以像这样在渲染方法中使用该方法吗?如果不是,我将如何做我想在这里做的事情:

import React, { Component } from 'react';
import { withMyHOC } from '../with_my_component'

class MyComponent extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { methodFromHOC }= this.props;
    const result = methodFromHOC(someArgument);

    return (
      <div >
        {result}
      </div>
    )
  }
}

export default withMyHOC(MyComponent );

当你说不要在 render 方法中使用 HOC 时,这意味着你不应该在另一个组件的 render 方法中创建 HOC 包装的组件的实例。例如,如果你有一个使用 MyComponent 的 App 组件,它不应该像下面这样

import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { methodFromHOC }= this.props;
    const result = methodFromHOC(someArgument);

    return (
      <div >
        {result}
      </div>
    )
  }
}

export default MyComponent;

import { withMyHOC } from '../with_my_component'
export default class App extends React.Component {
   render() {
      const Wrap = withMyHOC(MyComponent);
      return (
        <div>
            {/* Other Code */}
            <Wrap />
        </div>
      )
   }
}

为什么你不应该像上面那样使用它是因为每次调用 render 方法时,都会创建一个 MyComponent 的新实例,由名为 Wrap 的 HOC 包装,因此每次都会再次安装它而不是通过自然生命周期或 React。

但是,如果您的 HOC 将函数作为 props 传递,您可以在渲染中使用它,只要它不会再次导致重新渲染,否则会导致无限循环。

另外,直接在render中调用的函数最好memoize,避免反复计算

CodeSandbox Demo

A High Order Componentfunction,而 returns 是 Component,而不是 jsx。使用 hoc 包装组件时,您并没有更改组件的返回值,而是更改了签名本身。考虑以下 hoc

const withFoo = Component => props =>{
    return <Component {...props} foo='foo' />
}

withFoo 是一个 function,它将 Component(不是 jsx)作为参数,returns 是一个组件。您不需要从 render 调用 hoc,因为它注入的值已经在包装组件的 props 中。

hoc 告诉包装组件的外观,更改它的定义,因此唯一可以使用它的地方是在组件定义本身。在 render 中调用 hoc 会在每个 render 上创建该组件的新实例。相当于

const Component = () =>{
    const ChildComponent = () =>{
        return <span> Child </span>
    }

    return <ChildComponent /> //You're declaring again on each render
} 

像这样使用你的高阶组件

 const Component = ({ foo }) => <div>{ foo }</div>
 export default withFoo(Component)

const Component = withFoo(({ foo }) => <div>{ foo }</div>)