“ this”在反应高阶分量

时间:2018-11-25 10:16:23

标签: javascript reactjs

我想将共享功能从我的React组件移到像这样的高阶组件:

function withListFunctions(WrappedComponent) {
    return class extends React.Component {
        constructor(props) {
            super(props);
        }
        // my shared functionality
        deleteItem() {
            // Do something, then ...
            this.setState({itemDeleted: true});
        }
        render() {
            return (
                <WrappedComponent
                    deleteItem={this.deleteItem}
                 />
            );
        }
    }

使用这种语法需要在HOC的构造函数中显式绑定this

this.deleteItem = this.deleteItem.bind(this);

..但是我想绑定包装的组件。所以我在包装组件的构造函数中尝试的是

this.props.deleteItem = this.props.deleteItem.bind(this);

但这只会导致“无法分配为只读属性”错误,因为react道具是只读的。

我知道我可以将状态项存储在HOC中并作为道具传递给它。但是其他包装的组件函数将无法再访问(可写),对吗?我想知道是否有一种方法可以共享未绑定的函数,然后将其绑定到包装的实例。

[编辑] 我将Abdul Rauf的回答标记为“已接受”,但是我想指出Karen Grigoryan的答案是我实际上正在使用的解决方案,因为它可以工作,并且似乎恰好适合我的应用程序的复杂性。

2 个答案:

答案 0 :(得分:2)

  

我知道我可以将状态项存储在HOC中并传递它   下来作为道具。但这将不再可访问(可写)   通过其他包装的组件功能,对吧?

您应该将共享状态存储在HOC中。您可以将多个状态更新方法传递给Wrapped组件,它们可以在内部调用以间接更新状态。

如果您不想通过多种状态更新方法,则我们有2种选择:

选项1:在HOC中创建一个单独的dispatch方法,该方法采用action和可选的payload并将其传递给Wrapped组件。

// Do not mutate state in reducer. always return a new state
reducer(state, action) {
  switch (action.type) {
    case 'delete':
      // return final state after delete
    case 'add':
      // return final state after add using action.payload
    case 'update':
      // return final state after update using action.payload
    default:
      // A reducer must always return a valid state.
      // Alternatively you can throw an error if an invalid action is dispatched.
      return state;
  }
}


dispatch(action) {
    const updatedState = this.reducer(this.state, action)
    this.setState(updatedState);
}

选项2:,如果可以在挂钩支持下使用最新的React,请使用useReducer hook

  

我想知道是否有一种方法可以共享未绑定的函数,然后   将其绑定到包装的实例。

从技术上讲,您可以这样做(Check Karen Grigoryan's answer)。但是由于许多原因,这被认为是不好的做法。其中几个是:

  1. 它违反封装原则。 (状态在子组件中,状态更新逻辑在父组件中)。父组件应该对子组件的状态一无所知。

  2. 道具可以随时间变化,但不会自动反映在派生的Instance properties/fields

答案 1 :(得分:2)

props仅由design读取。

  

反应元素是不可变的。创建元素后,您将无法更改其子级或属性。元素就像电影中的单个帧一样:它表示特定时间点的UI。

因此,从技术上讲,将deleteItem绑定到WrappedComponent上下文的一种方法是将bind绑定到WrappedComponent constructor

codesandbox example

this.deleteItem = this.props.deleteItem.bind(this);