简体   繁体   English

如何将属性从有状态组件传递到包装子组件的 HOC 中使用的事件处理程序?

[英]How can I pass attributes from a stateful component to an event handler used in an HOC wrapping a child component?

I am using a framework where I must pass an event handler into an HOC that is wrapping one of the children of my stateful Page component.我正在使用一个框架,我必须将一个事件处理程序传递给一个 HOC,该 HOC 包装了我的有状态 Page 组件的一个子组件。

<Page>
    <HOC onClick={fn}>
        <PageColumn>
        </PageColumn>
    </HOC>
</Page>

I have a function in my stateful Page component that relies on the state and props of page.我的有状态页面组件中有一个 function 依赖于 state 和页面道具。 I must use a HOC that wraps a child component of the page.我必须使用包装页面子组件的 HOC。 Within this HOC I must call an onClick method that relies on the state of the Page component.在这个 HOC 中,我必须调用依赖于 Page 组件的 state 的 onClick 方法。

So far I have tried passing down a reference to this.state in order to use the Page state in the HOC, and I have tried passing down props that are assigned the values that I needed in the parent state.到目前为止,我已经尝试传递对 this.state 的引用,以便在 HOC 中使用页面 state,并且我已经尝试传递在父 Z9ED39E2EA9312EF573E 中分配了我需要的值的道具In the onClick fn, whether I reference the necessary properties by using this.state or this.props, I get the error:在 onClick fn 中,无论我使用 this.state 还是 this.props 引用必要的属性,我都会收到错误消息:

 cannot read property '<attribute>' of undefined

How can I successfully implement this pattern?我怎样才能成功地实现这种模式?

There is not a lot to investigate from you code.您的代码没有太多需要调查的地方。 I noted that you use HOC as a component, but usually hoc are functions that add something to a component.我注意到您使用 HOC 作为组件,但通常 hoc 是向组件添加某些内容的函数。

Usually hoc works like this:通常 hoc 是这样工作的:

EnrichedComponent = hoc(options)(BaseComponent); EnrichedComponent = hoc(options)(BaseComponent);

example: react-redux connect hoc function例如:react-redux connect hoc function

This approach should work:这种方法应该有效:

// render Page somewhere
const App = () => (
  <Page/>
)

// let Page component render the PageColumn component
class Page extends React.Component {
  handleClick() {
    // I can access page state and props
    const {
      state: { foo },
      props: { bar },
    } = this;

    console.log(foo, bar);
  }

  render() {
    return (
      <PageColumn onClick={this.handleClick} />
    )
  }
}

// wrap component with HOC
const PageColumn = hoc()(() => {
  return (
    <div>...</div>
  )
});

Take a look at the code below.看看下面的代码。 Basically, you want to create the function in your top level component and bind it to this in the constructor.基本上,您想在顶级组件中创建 function 并在构造函数中将其绑定到this Then pass it down as a property to your child component (ie no parameter list, no function syntax, just `this.myFunc').然后将它作为属性传递给您的子组件(即没有参数列表,没有 function 语法,只有 `this.myFunc')。

In the child component, in the onClick event, call the function and pass in your parameters.在子组件中,在 onClick 事件中,调用 function 并传入您的参数。 Use the name of the attribute of the parent function to call the function.使用父 function的属性名称调用 function。 So for example, here it's still this.props.myFunc , but if <Page /> had this expression instead: mySpecialFunc={this.myFunc} you would call like this instead <HOC onClick={(prm1,prm2,prm3) => this.props.mySpecialFunc(prm1,prm2,prm3)} />例如,这里仍然是this.props.myFunc ,但如果<Page />有这个表达式: mySpecialFunc={this.myFunc}你会这样调用<HOC onClick={(prm1,prm2,prm3) => this.props.mySpecialFunc(prm1,prm2,prm3)} />

In <Page /> :<Page />中:

constructor(){
   //regular constructor code

   this.myFunc = this.myFunc.bind(this);
}

myFunc(prm1, prm2, prm3){\
   //function code
   //
   this.setState({
      myFuncState: "newValue",
      //additional code
   });
}

render(){
    return (
        <Page>
            <HOC myFunc={this.myFunc}>
                <PageColumn />
            </HOC>
        </Page>
    )
}

In <HOC /> :<HOC />中:

render(){
    prm1 = "someValue1";
    prm2 = "someValue2";
    prm3 = "someValue3";
    return (
        <div className="HOC" onClick={(prm1,prm2,prm3) => this.props.myFunc(prm1,prm2,prm3)}>
    )
}

A Note on Parameters: The above code is for the situation where all of your parameters are in one place (in this case, the direct child component).关于参数的说明:上面的代码适用于所有参数都在一个位置(在本例中为直接子组件)的情况。 Sometimes they are spread out amongst parent, child, grandchild components, etc. In that case, you need to declare the parameters generically in each component, passing in the relevant parameters as you move down the chain of component ancestry .有时它们分布在父组件、子组件、孙子组件等之间。在这种情况下,您需要在每个组件中通用声明参数,并在您沿着组件祖先链向下移动时传递相关参数 For example:例如:

class Parent extends React.Component{
    constructor(){
        //normal render code
        this.passedFunc = this.passedFunc.bind(this);
    }

    passedFunc(prm1,prm2){
        //function code
        this.setState({
            a: val1,
            b: val2,
            //etc.
        })
    }

    render(){
        return (
            <Child passedFunc={this.passedFunc}
        )
    }  
}

class Child extends React.Component{
    //other relevant code

    render(){
        let val1 = "foo";

        return (
            //we're passing prm1 into the func as val1. <Child /> doesn't know what prm2 is so we're keeping that generic and letting <GrandChild /> handle it   
            <GrandChild passedFunc={(prm1, prm2) => this.props.passedFunc(val1, prm2)}
        )
    }
}

class GrandChild extends React.Component{
    //other relevant code

    render(){
        let val2 = "bar";

        return (
            //<GrandChild /> doesn't know what prm1 is, but it knows that prm2 is val2, so it's passing in prm2 as val2 and leaving prm1 generic so <Child /> can handle it
            <div passedFunc={(prm1, prm2) => this.props.passedFunc(prm1, val2)}
        )
}

As you can see, each component passes parameters up to their parent component and uses the generic parameter name for params they don't know.如您所见,每个组件都将参数传递给它们的父组件,并为它们不知道的参数使用通用参数名称。 Finally, the parent component receives all of the parameters and is able to use them in the function.最后,父组件接收所有参数并能够在 function 中使用它们。 If there was a middle man component in the chain that didn't need to set any params, for example a component named between <Child /> and '' named <InBetween /> , you could simply pass the function name through that component as a simple property, like this:如果链中有一个不需要设置任何参数的中间人组件,例如名为<Child />和名为<InBetween />的组件,您可以简单地将 function 名称通过该组件传递为一个简单的属性,像这样:

<InBetween passedFunc={this.props.passedFunc} />

Any parameters set in a component above or below it in the chain will remain intact.在链中位于其上方或下方的组件中设置的任何参数都将保持不变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM