[英]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.