首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在显示redux状态变化时的问题

在显示redux状态变化时的问题
EN

Stack Overflow用户
提问于 2020-05-26 00:40:24
回答 2查看 815关注 0票数 0

更新到最初的文章:我已经意识到问题在于,Redux状态( WaitingRoom组件的支持)中的更新以某种方式将组件的整个状态设置为初始状态。因此,“显示匹配窗口”也被设置为false。最初,在分派MATCHING_REQUEST并将“加载”设置为true之后,WaitingRoom组件的状态仍然保持不变。但是,在发出MATCHING_SUCCESS并将"loading“变为false之后,Redux状态中的”好友“和"chatid”被更新后,处于WaitingRoom状态的所有字段都会以某种方式重置为它们的初始值。这很奇怪,在我的其他Redux操作中没有发生。我想知道是否有人能帮我解释一下是什么原因造成的。非常感谢你的耐心和任何你能提供的帮助!

链接到Github 项目 (WaitingRoom组件位于src/components/等候室. is中)

/下面是最初的post/

我正在为我的网站建立一个随机匹配功能。,这里有一个简短的描述,:一旦两个用户成功匹配,我想要一个聊天窗口弹出。在我的Redux状态中,我有(1)“加载”( chat ),(2)“好友”表示与当前用户匹配的用户的id,(3) "chatid“表示存储两个用户之间聊天历史的防火墙文档的id。startMatching Redux操作在WaitingRoom组件中调用,该组件是一个网页,除了具有匹配按钮外,还显示其他用户的配置文件。chat窗口是MatchingWindow组件,它需要一个chatid作为其支持,以在两个用户之间呈现相应的聊天历史记录。

我确信我的Redux操作工作良好,但是在将更新的Redux状态传递给我的React组件时遇到了问题。下面是我尝试过的两种方法:

方法1:在WaitingRoom组件返回的模式中显示聊天窗口。正如您所看到的,我在这里所做的只是有条件的呈现。然而,使用这种方法,该模式很快就会出现在不到一秒钟的时间内,然后随着用户选择其性别偏好的前一个模式而消失。通过检查WaitingRoom组件的道具,我发现“好友”和"chatid“确实被更新了。MatchingWindow不应该呈现吗?我还试着只使用success>而不是MatchingWindow组件,结果是一样的。

方法1 (WaitingRoom)

代码语言:javascript
复制
class WaitingRoom extends Component {

    state = {
      ......
    }

    showMatching = (e) => {
      e.preventDefault();
      this.setState({
        showmatching: true
      })
    }

    handleMatching = (e) => {
      e.preventDefault();
      this.props.startMatching(this.props.auth.uid, this.props.profile, this.props.profile.gender, this.state.genderpreference);
      this.setState({
        showmatchingwindow: true
      })
    }

    closeMatching = () => {
      this.setState({
        showmatching: false
      })
    }


      render() {

        const { auth, users, profile, loading, sent, buddy, chatid } = this.props;


        return (

            <div>
            <Button variant="success" onClick={this.showMatching} style={{ fontSize: "large", fontFamily: "Comic Sans MS, cursive, sans-serif"}}>Randomly find a study/work buddy instantly!</Button>
            </div>


            <Modal show={this.state.showmatching} onHide={this.closeMatching}>
              <Modal.Header closeButton></Modal.Header>
              <Modal.Body>
                <form onSubmit={this.handleMatching}>
                  Match me with:
                  <div className="form-inline">
                        <div className="radio-container">
                            <label>Male only</label><input type="radio" id="genderpreference" value="Male" onChange={this.handleChange} checked={this.state.genderpreference === "Male"} />   
                        </div>

                  ......

                  </div>

                  <button>Start matching</button>
                </form>
              </Modal.Body>
            </Modal>

            <Modal show={this.state.showmatchingwindow} onHide={this.closeMatching}>
              <Modal.Header closeButton></Modal.Header>
              <Modal.Body>
                { loading ?  <div class="loader"></div> : null}
                { buddy !== "" && loading === false ? <MatchingWindow chatid=chatid /> : null }
                { buddy === "" && loading === false ? <span>Sorry we cannot help you find a study/work buddy currently</span> : null }
              </Modal.Body>
            </Modal>

        );
      }
    }

const mapStateToProps = (state) => {
  return {
    users: state.firestore.ordered.users,
    auth: state.firebase.auth,
    profile: state.firebase.profile,
    loading: state.auth.loading,
    sent: state.auth.sent,
    buddy: state.auth.buddy,
    chatid: state.auth.chatid
  }
}

export default compose(
connect(mapStateToProps, {submitTicket, startMatching, groupMessaging}),
firestoreConnect([
{ collection: 'users' }
])
)(WaitingRoom);

方法2:创建一个单独的MatchingBox组件,它将根据不同的状态呈现不同的元素/组件。但是,当我采用这种方法时,componentWillReceiveProps()并不是在Redux状态更改之后触发的,因为我放置在方法中的console.log()没有被执行。这很奇怪,因为正如我在方法1中提到的那样,当我检查WaitingRoom组件的道具时,Redux状态确实发生了变化,这意味着我的Redux操作和还原程序代码应该很好,对于MatchingBox组件也应该是一样的。由于componentWillReceiveProps()没有被触发,我传递给MatchingWindow组件的chatid是一个空字符串,这是有问题的。我尝试了componentDidUpdate(),但它也不起作用。

方法2 (WaitingRoom)

代码语言:javascript
复制
class WaitingRoom extends Component {

      render() {

        return (

            ......All the same except for replacing the second Modal with:
            { this.state.showmatchingwindow ? <MatchingBox /> : null }

        );
      }
    }

方法2 (MatchingBox)

代码语言:javascript
复制
class MatchingBox extends Component {

    state = {
        loading: true,
        chatid: "",
        buddy: []
    }

    componentDidMount() {
        console.log(this.props.loading);
        console.log(this.props.chatid);
        console.log(this.props.buddy);
        this.setState({
            loading: this.props.loading,
            chatid: this.props.chatid,
            buddy: this.props.buddy
        })
    }


    componentWillReceiveProps() {
        console.log(this.props.chatid);
        console.log(this.props.buddy);
        this.setState({
            loading: this.props.loading,
            chatid: this.props.chatid,
            buddy: this.props.buddy
            })
        }

    render() {
        let box;
        if (this.props.loading === true) {
            box = <div class="loader"></div>
        }
        else {
            if (this.props.buddy !== "") {
                box = <div>
                <MatchingWindow chatid={this.state.chatid} />
                </div>    
            }
            else {
                box = <span>Sorry</span>
            }
        }
        return (
            <div>
                {box}
            </div>

        );
    }

}

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操作

代码语言:javascript
复制
export const startMatching = (userid, userprofile, usergender, genderpreference) => (dispatch) => {

    dispatch({ type: MATCHING_REQUEST });

    ......

    dispatch(matchingConversation(userspool[number].id, doc.data(), userprofile, {time: "", from: "", content: ""}, number, userspool));      
}

export const matchingConversation = (user2id, user2profile, user1profile, message, number, userspool) => (dispatch, getState) => {

      .....
                .then(() => {
                    dispatch({ type: CHAT_SUCCESS, payload: doc.id });
                })
                .then(() => {
                    dispatch({ type: MATCHING_SUCCESS, payload: user2id });
                })
}

渣油减速器

代码语言:javascript
复制
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;
    }
}
EN

回答 2

Stack Overflow用户

发布于 2020-05-26 07:54:34

首先,我不认为你需要使用任何内部状态。当您知道多个组件必须共享相同的变量,并且它们不是层次结构时,只需使用存储和使用应用程序状态即可。

其次,我认为在还原器中,您可能指向相同的初始状态并直接改变它(违反redux规则)。简而言之,由于浅表复制,您的状态可能指向同一个旧的初始状态对象,因此您的react组件没有检测到更改。

在返回新状态之前,尝试在redux还原器中创建初始状态的深层副本(而不是浅副本)。这些链接讨论了这些概念:

  1. https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns
  2. 当存储状态更改时,响应组件不更新

最后,处于初始状态的伙伴不应该是空数组而不是字符串吗?

票数 0
EN

Stack Overflow用户

发布于 2020-05-29 03:26:37

您似乎使用了一个函数来返回组件:

代码语言:javascript
复制
// main.js
const WaitingRoomPage = () => {
  return <WaitingRoom />;
};

...

<Route path='/waitingroom' component={WaitingRoomPage} />

我认为您不应该这样做,因为Main的每次重呈现都会导致WaitingRoom保留重新安装(从而重新初始化)。您的WaitingRoom不是一个功能组件,即使是这样,您仍然应该使用更简单的方法来声明具有component属性的Route

代码语言:javascript
复制
<Route path='/waitingroom' component={WaitingRoom} />
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62012881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档