![](/img/trans.png)
[英]redux-thunk: Pause Component Execution Until Action Creator Completes
[英]How to turn redux-thunk action creator into Promise?
我有以下異步動作創建者(使用redux-thunk):
export const nextPupil = () => {
return (dispatch, getState) => {
const {activeSentence, sentencesList} = getState();
//... some more code
const nextActive = pupilList[nextIndex];
dispatch({ type: "UPDATE_ACTIVE", payload: nextActive });
}
};
但是,我需要執行此操作以返回承諾,因為我需要在我的一個組件中等待其完成,然后再執行其他操作(請參閱此問題以獲取有關我的問題的更詳細說明)
我該如何將這個動作變成一個承諾並仍然使用redux-thunk? 非常感謝。
編輯:
我知道我正在嘗試將輸入字段的狀態保存在本地組件中,而不是保存在Redux中。 這是因為如果我將輸入字段的值直接綁定到redux存儲,它將不再可編輯。 但是,我希望用戶能夠編輯輸入字段,然后在提交時將編輯后的值保存在我的redux存儲中。 如果我直接綁定東西,則用戶將無法更改值/進行編輯。
我認為您誤解了通過redux的數據流。 我假設當您要將操作轉變為一個承諾時,您希望該承諾在更新redux狀態時得到解決-另一個問題似乎就是這種情況。 通常,這不是設計redux的方式。
當您分派動作時,商店將被更新,然后來自商店的組件中的道具將被更新。 您需要做的就是在組件中使用這些道具,並且只要道具更新,組件也將使用。
在最初的問題中,您的代碼是:
onSubmit(e) {
e.preventDefault();
this.props.nextSentence(); //this is async
this.setState({ //this is not yet updating with the right values then
inputField: this.props.activePupil.name
});
}
您遇到的問題是, activePupil
是您的redux存儲的一部分,但是您也試圖將其存儲在組件的狀態內。 這是一個壞主意,因為您再也無法為自己的狀態提供單一的真理來源。
更好的方法是在需要的地方使用this.props.activePupil
,例如
render() {
return (
<span>{this.props.activePupil.name}</span>
);
}
現在,當您分派操作時,存儲一經更新,組件也會隨之更新。 如果需要,則可以在商店中添加loading
屬性,以便可以向用戶指示正在發生的事情,並在執行任何異步工作之前從thunk中分派此事件,然后在分派UPDATE_ACTIVE
時恢復loading
。
export const nextPupil = () => {
return (dispatch, getState) => {
dispatch({ type: "PUPIL_UPDATING });
const {activeSentence, sentencesList} = getState();
//... some more code
const nextActive = pupilList[nextIndex];
dispatch({ type: "UPDATE_ACTIVE", payload: nextActive });
}
};
我們花了點時間考慮下面的解決問題的正確方法,但是我認為我已經確定了一種合理的方法來實現它,同時又保持了數據完整性。 它確實涉及將表單輸入保存在您的商店中,並不是每個人都喜歡它,但對我來說不是問題。
無論如何...我們需要另一個reducer來處理用戶輸入-這將非常簡單並響應兩個動作-您已經擁有的“ UPDATE_ACTIVE”動作和“ NAME_UPDATED”動作:
const updatedName = (state = '', action) => {
switch (action.type) {
case 'UPDATE_ACTIVE':
return action.payload.name;
case: 'NAME_UPDATED':
return action.payload.updatedName;
default:
return state;
}
};
然后,我們將需要一個簡單的動作創建者:
const inputChanged = updatedName => ({
type: 'NAME_UPDATED',
payload: { updatedName }
});
現在,在我們的組件中,我們將使用新創建的狀態和動作創建者來管理我們的輸入(只需照常connect
它們)-這里缺少很多代碼,但應該足夠理解。
class Whatever extends React.Component {
constructor() {
super();
this.handleChange= this.handleChange.bind(this);
}
handleChange(event) {
this.props.inputChanged(event.target.value);
}
render() {
return (
<input type="text" value={this.props.updatedName} onChange={this.handleChange} />
);
}
}
我希望這是有道理的!
如果您想將輸入存儲在組件狀態上而不是在redux存儲中,那么我認為這種方法應該可行。 它使用componentWillReceiveProps生命周期掛鈎 -設置組件狀態,即activePupil
更改時的輸入值。 每次道具更新時都會調用此方法,但是在道具沒有任何更改時也可能會調用它,因此我們需要一些邏輯來決定是否更新updatedPupilName
道具。 為此,我們將當前的props.activePupil.name
與nextProps.activePupil.name
進行比較,並且僅在狀態不同時才更新狀態。 如果您的學生具有ID類型屬性,則可能更適合進行比較。
class Whatever extends React.Component {
constructor(props) {
super(props);
this.state = {
updatedPupilName: props.activePupil.name
};
this.handleChange= this.handleChange.bind(this);
}
componentWillReceiveProps(nextProps) {
if (nextProps.activePupil.name !== this.props.activePupil.name) {
this.setState({
updatedPupilName: nextProps.activePupil.name
});
}
}
handleChange(event) {
this.setState({
updatedPupilName: event.target.value
});
}
render() {
return (
<input type="text" value={this.state.updatedPupilName} onChange={this.handleChange} />
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.