顺序派遣动作的Redux

问题描述 投票:1回答:1

我正在为我的网站构建一个随机匹配功能。在startMatching Redux动作结束时,如果匹配成功,我想在调度MATCHING_SUCCESS之前调度另一个叫做startConversation的动作。startConversation动作用于创建或更新2个用户之间的聊天记录,并会在最后调度存储聊天记录的firestore文档的id作为有效载荷。由于(1)startConversation是在MATCHING_SUCCESS之前派发的,(2)startConversation派发的是聊天记录文档的id,所以我可以在Redux状态下创建一个名为chatid的字段,以便在匹配成功后访问文档的id,并使用它来生成类似聊天窗口的东西。

我一直在用匹配应该成功的情况下测试代码。我得到的问题是,第一个调度(startConversation)是在第二个调度(matching_success)完成后完成的。我之所以知道这一点,是因为我把console.log放在了MatchingBox组件的componentDidUpdate方法和startConversation动作的最后,前者的console.log比后者执行的早,也就是说MATCHING_SUCCESS在startConversation之前就完成了调度,这就造成了Redux状态的改变,从而对组件进行了道具。的确,MatchingBox组件状态中的buddy和loading字段被更新了,chatid仍然是一个空字符串。我不希望这种情况发生,因为如你所见,我需要将chatid进一步传递给MatchingWindow组件。

这让我很困惑。毕竟,Redux不是同步的吗?另外,我试着用 "then "将2个派遣链起来,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);      
}

重修减速器

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;
    }
}

MatchingBox组件

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 react-redux redux-thunk react-redux-firebase redux-firestore
1个回答
0
投票

看起来你使用的是redux thunk,而且作为 文件 说道:"Redux Thunk中间件允许你编写返回函数而不是动作的动作创建者。

Redux Thunk中间件允许你编写动作创建者,返回一个函数而不是动作。Thunk可以用来 拖延 派遣一个动作,或者只在满足某个条件时才派遣。内部函数接收存储方法dispatch和getState作为参数。

你的动作还原器 startConversation 这样一来,redux thunk就会保留这个dispatch,直到它被解决,但不会阻止下面的代码被执行。

下一行 MATCHING_SUCCESS 立即执行,而不是等待前一个悬而未决的问题被解决。同样地。MATCHING_FAIL 是在承诺之外的,可能在所有派遣之前被触发(除了 MATCHING_REQUEST).

既然 startConversation 是异步的,而你需要在其解析后执行这些派遣,你应该考虑调用 MATCHING_SUCCESSMATCHING_FAILstartConversation.

© www.soinside.com 2019 - 2024. All rights reserved.