在react中将动态值传递给 HOC

IT技术 reactjs high-order-component
2021-05-04 19:28:50

我写了一些 HOC,我需要将我在某个生命周期级别创建的动态对象传递给这个 HOC,但我没有将他作为props。如果我尝试传递一些静态值(例如从一开始初始化 myObj),它会按预期工作并且我得到正确的值。

假设这是我的组件类:

 let myObj = {};

  class Test extends React.Component
   {
      constructor(props) {
        super(props);
        .....
        }

         render() {
            myObj = {test:'test'};
            return ( ... )
        }       
    }
   export default withHOC(Test, myObj);

这是我的 HOC:

const withHOC = (Component, test) => {
    class Hoc extends React.Component
    {
        constructor(props)
        {
            super(props);
            const s = test; // ---->test is empty object always !!
            ...
        }

     } 
     return Hoc;
 }

我在“测试”类上创建的“动态”对象在 HOC 类中始终为空。当我尝试直接从我的props传递一些值时也会发生这种情况,在这种情况下页面卡住了(控制台中没有错误)。

有人知道如何解决这个问题吗?谢谢!

4个回答

当您以这种方式组合组件时,组合仅在编译时发生(静态组合)。这意味着 withHOC 只运行一次并且接收一个空myObj参数,因为它使用的是在声明中定义的参数。

export default withHOC(Test, myObj); //myObj = {}

如果您希望该值是动态的,withHOC则应在该值更改时运行组合。

您无法将数据从WrappedComponent(Test) 发送到HOC(withHOC),因此即使您更改 中的myObjTest.render,HOC 也永远不会知道。

如果你真的需要的话,你可以做的是在 Test.render

render(){
    const Hoc = withHOC(this.state.myObj, WrappedComponent);//WrappedComponent can be anything
    return(
        <Hoc/>
    )
}

这样,每次组件渲染时,Hoc都使用myObj组件状态中的值进行组合,这不是最好的方法,因为 this.state.myObj 可能具有与上一次渲染时相同的值,并且您将使用与以前相同的数据重新组合。

更好的方法是检查 myObj 中的Test.componentDidUpdate更改,如果更改,则Hoc再次撰写

您正在将一个空对象传递给withHOC函数

let myObj = {}; // <- your myObj is empty

  class Test extends React.Component
   {
      constructor(props) {
        super(props);
        .....
        }

         render() {
            myObj = {test:'test'}; // <- You're doing this in the render method of your Test component, so until the component is rendered myObj is empty
            return ( ... )
        }       
    }
   export default withHOC(Test, myObj);

关于这里发生的事情的一些解释,按顺序:

  1. import Comp from '.../Test.js'
  2. withHOC功能被触发,随着PARAMS Test(其呼叫上述定义相同)和myObj(其呼叫上面定义的,但为空)
  3. 测试组件返回,没有人使用的逻辑 myObj = {test:'test'}

建议的解决方案:让 HOC 使用另一个 hoc 从props中获取逻辑:

const withProps = newProps => BaseComponent => props => {
  const propsToAdd = typeof newProps === 'function' ? newProps(props) : newProps
  return <BaseComponent {...props} {...propsToAdd} />
}

用法:

class Test extends React.Component
   {
      constructor(props) {
        super(props);
        .....
        }

         render() {
            return ( ... )
        }       
    }
export default withProps({test:'test'})(withHOC(Test));
// or: export default withProps(props => {test:'test'})(withHOC(Test));

const withHOC = (Component) => {
    class Hoc extends React.Component
    {
        constructor(props)
        {
            super(props);
            const s = this.props.test;
            ...
        }

     } 
     return Hoc;
 }

您可以使用recompose,这是一个具有许多 hoc 和 utils 的库,并且具有更好的可读性:

import { compose, withProps } from "recompose"

class Test extends React.Component {...}

const enhance = compose(
  withProps({test:'test'}),
  withHOC
)
export default enhance(Test);

我不能自信地说这是最佳的,但我通过在 HOC 中使用更新状态的函数解决了类似的问题,然后您可以使用包装组件中的任何数据调用该状态。

霍克:

func = (a, b) => {
  this.setState({
    stateA: a,
    stateB: b
  )}
}

return ({ <WrappedComponent func={this.func} /> })

包裹组件:

this.props.func(anythingA, anythingB);

然后,您可以通过 HOC 中的状态访问数据。

详细说明:

const withHOC = (WrappedComponent) => {
  class withHOC extends React.Component {
    constructor(props) {
      super(props)

      this.state = {
        stateA: 1,
        stateB: 2
      }
      *use state however you want in this HOC, including pass it through to another component*

      *the following is just a function*
      *when it's invoked in the wrapped component state will update here in the 
 HOC*
      changeState = (a, b) => {
        this.setState({
          stateA: a,
          stateB: b
        )}
      }

      render() {
        return (
          <div>
            <p>this.state.stateA</p>
            <p>this.state.stateB</p>
            <WrappedComponent changeState={this.changeState} />
          </div>
        )
      }
    }
  }
}

在wrappedComponent中,导入后:

class aComponent extends Component {
  constructor(props) {
    super(props)

    this.state = {
    }

    *you can now invoke the function from the HOC in this wrapped component*
  }
}