我正在为我的网站构建一个随机匹配功能。在 startMatch Redux 操作结束时,如果匹配成功,我想在调度MATCHING_SUCCESS之前调度另一个名为 startConversation 的操作。startConversation 操作用于创建或更新 2 个用户之间的聊天历史记录,并将调度将聊天历史记录存储为最后有效负载的 firestore 文档的 id。由于 (1( startConversation 是在MATCHING_SUCCESS之前调度的,(2( startConversation 调度聊天历史文档的 id,我可以在我的 Redux 状态下创建一个名为 chatid 的字段,以便在匹配成功完成后访问文档的 ID,并使用它来生成类似聊天窗口的内容。
我一直在测试代码,其中应该成功完成匹配。我得到的问题是,第一次调度(startConversation(是在第二次调度(MATCHING_SUCCESS(完成后完成的。我知道这一点,因为我将控制台.log放在 MatchingBox 组件的 componentDidUpdate 方法中,并在 startConversation 操作结束时,而前者的控制台.log比后者更早执行,这意味着MATCHING_SUCCESS在 startConversation 之前完成了调度,这导致了 Redux 状态的变化,从而支持组件。事实上,处于 MatchingBox 组件状态的好友和加载字段已更新,聊天记录仍为空字符串。我不希望这种情况发生,因为正如你所看到的,我需要将chatid进一步传递给MatchingWindow组件。
这让我感到困惑:毕竟,Redux 不是同步的吗?此外,我尝试将 2 个调度与"then"链接起来,并且 startConversation 仍然晚于 MATCHING_SUCCESS 完成调度。我想知道如何解决这个问题。非常感谢您的耐心等待!
冗余操作
export const startConversation = (user2id, user2profile, user1profile, message) => (dispatch, getState) => {
......
console.log(chatid);
dispatch({ type: CHAT_SUCCESS, payload: chatid });
}
export const startMatching = (userid, userprofile, usergender, genderpreference) => (dispatch) => {
dispatch({ type: MATCHING_REQUEST });
...Matching algorithm...
//Dispatches
firebase.firestore().collection("users").doc(userspool[number].id).get()
.then((doc) => {
dispatch(startConversation(userspool[number].id, doc.data(), userprofile, {time: "", from: "", content: ""}));
dispatch({ type: MATCHING_SUCCESS, payload: doc.data() });
})
if (buddy === "") {
dispatch({ type: MATCHING_FAIL, payload: [] });
}
console.log(buddy);
}
Reux reducer
const initialState = {
......
loading: false,
chatid: "",
buddy: [],
}
const authReducer = (state = initialState, action) => {
const {type, payload} = action;
switch(type) {
......
case CHAT_SUCCESS:
return {
...state,
chatid: action.payload
}
case MATCHING_REQUEST:
return {
...state,
loading: true
}
case MATCHING_SUCCESS:
return {
...state,
buddy: action.payload,
loading: false
}
case MATCHING_FAIL:
return {
...state,
buddy: action.payload,
loading: false
}
default: return state;
}
}
匹配框组件
class MatchingBox extends Component {
state = {
show: true,
loading: false,
chatid: "",
buddy: []
}
componentDidMount() {
this.setState({
loading: this.props.loading,
})
}
componentDidUpdate(prevprops) {
console.log(this.props.chatid);
console.log(this.props.buddy.first_name);
if (prevprops.loading !== this.props.loading) {
this.setState({
loading: this.props.loading,
chatid: this.props.chatid,
buddy: this.props.buddy
})
}
}
render() {
let box;
if (this.props.loading === true) {
box = <span>Loading...</span>
}
else {
if (this.props.buddy.length !== 0) {
box = <div>
<div className="form-inline">
<img src={this.state.buddy.image}></img>
<img src={this.props.profile.image}></img>
</div>
<MatchingWindow chatid={this.state.chatid} />
</div>
}
else {
box = <span>Sorry we cannot help you find a study/work buddy currently</span>
}
}
return (
<Modal show={this.state.show}>
<Modal.Header closeButton></Modal.Header>
<Modal.Body>
{box}
</Modal.Body>
</Modal>
);
}
}
const mapStateToProps = (state) => {
return {
auth: state.firebase.auth,
loading: state.auth.loading,
chatid: state.auth.chatid,
buddy: state.auth.buddy,
profile: state.firebase.profile
};
}
export default connect(mapStateToProps)(MatchingBox);
看起来您正在使用 redux thunk,正如文档所说:
Redux Thunk 中间件允许您编写返回的动作创建者 函数而不是操作。捶打可以用来延迟调度操作,或仅在特定条件 遇到。内部函数接收存储方法调度和 获取状态作为参数。
你的动作减少器startConversation
做一些异步动作对吗? 这样,Redux Thunk 将保留该调度以执行直到其解决,但不会阻止执行以下代码。
下一行MATCHING_SUCCESS
立即执行,它不会等待待处理的前一行被解决。同样,MATCHING_FAIL
在承诺之外,并且可能在所有调度之前触发(MATCHING_REQUEST
除外(。
由于startConversation
是异步的,并且您需要在其解析后执行这些调度,因此应考虑在startConversation
调用MATCHING_SUCCESS
和MATCHING_FAIL
。