[英]“this” in react higher order component
我想將反應組件的共享功能移動到更高階的組件,如下所示:
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);
但這只會導致“無法分配給只讀屬性”錯誤,因為反應道具只是為了讀取。
我知道我可以將狀態項存儲在HOC中並將其作為道具傳遞下去。 但是,其他包裝的組件功能將無法訪問(可寫),對吧? 我想知道是否有一種方法可以共享未綁定的函數,然后將其綁定到包裝的實例。
[編輯]我將Abdul Rauf的回答標記為“已接受”,但我想說Karen Grigoryan的回答是我實際使用的解決方案,因為它的工作原理似乎只適合我的應用程序的復雜性。
我知道我可以將狀態項存儲在HOC中並將其作為道具傳遞下去。 但是,其他包裝的組件功能將無法訪問(可寫),對吧?
您應該在HOC中存儲共享狀態。 您可以將多個狀態更新方法傳遞給它們可以在內部調用的Wrapped組件,以間接更新狀態。
如果您不想傳遞多個狀態更新方法,那么我們有兩個選項:
選項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:如果您可以使用最新的鈎子支持反應,請使用useReducer
鈎子 。
我想知道是否有一種方法可以共享未綁定的函數,然后將其綁定到包裝的實例。
從技術上講,你可以做到這一點( 檢查Karen Grigoryan的答案 )。 但由於種種原因,這被認為是一種不好的做法。 其中很少是:
它反對封裝原則。 (State位於Child組件中,狀態更新邏輯位於父組件中)。 父組件不應該知道子組件的狀態。
道具可以隨時間變化,但這不會自動反映在派生的Instance properties/fields
props
只能通過設計閱讀。
React元素是不可變的。 創建元素后,您無法更改其子元素或屬性。 元素就像電影中的單個幀:它代表特定時間點的UI。
從技術上講,將deleteItem
綁定到WrappedComponent
上下文的方法之一就是在WrappedComponent
constructor
bind
它:
this.deleteItem = this.props.deleteItem.bind(this);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.