将动态值传递给HOC以做出反应

时间:2019-03-14 12:29:40

标签: reactjs high-order-component

我写了一些HOC,我需要将在某个生命周期级别上创建的动态对象传递给此HOC,但我没有把他当作道具。 如果我尝试传递一些静态值(例如,从开始初始化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类上始终为空。 当我尝试直接从道具传递一些值时也会发生这种情况,在这种情况下,页面会卡住(控制台中没有错误)。

有人知道如何解决吗?谢谢!

5 个答案:

答案 0 :(得分:1)

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

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

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

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

如果确实需要,您可以做的是Test.render

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

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

一种更好的方法是在Test.componentDidUpdate处检查myObj中的更改,如果更改了,请再次编写Hoc

答案 1 :(得分:0)

您要将空对象传递给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);

答案 2 :(得分:0)

按顺序对此处发生的情况进行了一些解释:

  1. import Comp from '.../Test.js'
  2. 使用withHOC(在调用上方定义)和Test(在调用上方定义但为空)的参数触发myObj函数。
  3. 返回了测试组件,没有人使用myObj = {test:'test'}的逻辑

建议的解决方案: 使得HOC可以从道具中获得逻辑:

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);

答案 3 :(得分:0)

我不能肯定地说这是最佳选择,但是我通过在HOC中拥有一个更新状态的函数来解决了类似的问题,然后可以使用包装的组件中的任何数据来调用状态。

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*
  }
}




答案 4 :(得分:0)

您可以使用react-redux并将对象存储为redux状态。随时随地更改对象(在情况下为Test),并从redux状态访问HOC内部组件中的对象,该对象将始终保持最新状态。