我想将共享功能从我的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的答案是我实际上正在使用的解决方案,因为它可以工作,并且似乎恰好适合我的应用程序的复杂性。
答案 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)。但是由于许多原因,这被认为是不好的做法。其中几个是:
它违反封装原则。 (状态在子组件中,状态更新逻辑在父组件中)。父组件应该对子组件的状态一无所知。
道具可以随时间变化,但不会自动反映在派生的Instance properties/fields
答案 1 :(得分:2)
props
仅由design读取。
反应元素是不可变的。创建元素后,您将无法更改其子级或属性。元素就像电影中的单个帧一样:它表示特定时间点的UI。
因此,从技术上讲,将deleteItem
绑定到WrappedComponent
上下文的一种方法是将bind
绑定到WrappedComponent
constructor
:
this.deleteItem = this.props.deleteItem.bind(this);