React / Redux - 带有Redux的子组件更新某些父状态更改,而不是其他更新

时间:2017-08-07 03:51:45

标签: javascript reactjs redux react-redux

在我的React应用程序中,我遇到了一个问题,即从Redux状态拉出的组件在其父组件的某些(但不是全部)状态更改期间不会更新 - 这会给我带来一些麻烦,并且我想了解为什么某些父组件状态更改正在注册而其他组件状态更改未注册。

我已经提供了以下父母(User.jsx)和子(MembershipList.jsx)组成部分的相关摘录,但简要总结一下,问题如下:

User.jsx中,函数addGroup将对象添加到'领导者'或者'会员' '组的数组属性' state对象 - 当状态更新时,使用来自这些对象的数据更新MembershipList.jsx。此功能正常,如下面的代码所示。

函数removeGroup应该与addGroup相反 - 它通过从组数组中删除对象来更新状态。目前,此函数已成功更新User.jsx的状态,但MembershipList.jsx子组件未更新以匹配。我认为这与在Membership.jsx中使用Redux状态有关,因为如果我只是将export default connect(mapStateToProps, undefined)(MembershipList)替换为export default MembershupList,则此功能可以根据需要运行 - 父级状态更新和孩子正确重新呈现。

User.jsx(摘录)

import React, {Component} from 'react';
import { connect } from 'react-redux';

class User extends Component{
    constructor(props){
        super(props);
        this.removeGroup = this.removeGroup.bind(this);
        this.state = {
            groups: {
                leader: [],
                member: []
            }
        }
    }

    // THIS FUNCTION SUCCESSFULLY UPDATES THE STATE AND THE MembershipList.jsx COMPONENT
    addGroup(groupData, grouprole) {
        let groupToAdd = JSON.parse(groupData)
        let groupsToUpdate = this.state.groups;
        groupsToUpdate[grouprole] = [...groupsToUpdate[grouprole], groupToAdd]
        this.setState({groups: groupsToUpdate})
    }

    // THIS FUNCTION SUCCESSFULLY UPDATES THE STATE,
    // BUT THE MembershipList.jsx COMPONENT FAILS TO UPDATE
    removeGroup(groupId, grouprole) {
        let groupsToUpdate = this.state.groups;
        for (let i = 0; i < groupsToUpdate[grouprole].length; i ++){
            if (groupId === groupsToUpdate[grouprole][i].id){
                groupsToUpdate[grouprole].splice(i, 1)
                this.setState({groups: groupsToUpdate})
            }
        }
    }

    render(){
        // ABBREVIATING - THIS IS THE RELEVANT COMPONENT
        <MembershipList
            groups={this.state.groups.leader}
            legend={"Leader"}
            removeGroup={this.removeGroup}
            parent="edit_user"
            grouprole={"leader"}
            openModal={this.openModal}
            hideModal={this.hideModal} />
    }

}

export default connect(undefined, mapDispatchToProps)(User);

MembershipList.jsx(摘录 - 这是User.jsx的某些状态更改无法更新的组件)

import React, { Component } from 'react';
import { connect } from 'react-redux';

const mapStateToProps = state => ({
    state
});

class MembershipList extends Component {
    constructor(props) {
        super(props);
        this.removeGroup = this.removeGroup.bind(this);
        this.modalReference = "group";
    }

    removeGroup(event){
        event.preventDefault();
        this.props.removeGroup(event.target.dataset.groupid, this.props.grouprole);
    }

    render() {
        let membershipList;

        if(this.props.parent === "edit_user" || this.props.parent === "new_user"){
            membershipList =    <ul className="membership_list">
                                    {
                                        this.props.groups.map((group, i) => (
                                            <li className="membership_list_item" key={i}>
                                                <a onClick={() => this.props.openModal(group.id, this.modalReference)}>{group.name}</a>
                                                <button className="remove_button btn btn-warning" onClick={this.removeGroup} data-groupid={group.id}>Remove</button>
                                            </li>
                                        ))
                                    }
                                </ul>
        }
        else{
            // HERE, membershipList IS A SIMILAR BIT OF HTML AS ABOVE, THOUGH IT REFERENCES THE REDUX STATE
            // HOWEVER, THIS CONDITION IS NOT EXECUTED DURING THE TROUBLESOME CHAIN OF EVENTS
        }

        return(
            <fieldset className="MembershipList">
                <legend>{this.props.legend}</legend>
                <div className="membership_list_container">
                    {membershipList}
                </div>
            </fieldset>
        );
    }
}

export default connect(mapStateToProps, undefined)(MembershipList)

除了我想修复这个问题之外,我想知道为什么会发生这种情况 - 为什么父状态改变会增加状态&#39中数组的长度?基团&#39;属性重新呈现子进程,而减少这些数组长度的父状态更改无法更新子进程?我已经在孩子的console.log函数中删除了一些render,并且在增加(addGroup)时会记录它们,但是当它们减少时不记录任何内容({{ 1}})。任何人都可以提出一些想法吗?

1 个答案:

答案 0 :(得分:2)

非常感谢@enjoylife指出我正确的方向...他/她真的值得称赞,但我回答了我自己的问题,因为我对这个问题的看法将使我能够提供更好的在这种情况下,形成的答案可能对其他人有所帮助。

简而言之,我的应用程序的原始结构是在父组件(User.jsx)中使用Redux,而不是在子组件(MembershipList.jsx)中使用Redux,以及我编写{ {1}}功能虽然可能不完美,但工作得很好。

但是,由于我个人不理解的原因,一旦我将Redux添加到该组件,该函数开始无法更新子组件 - removeGroup()返回原始数组的变异版本,而不是而不是新的数组,子组件不再响应源自splice()方法的状态的变化。

@enjoylife通过指出这一点击中了头 - 我需要一种更强大的更新状态的方法。我使用React splice()模块(https://github.com/kolodny/immutability-helper)来完成此任务。以下是immutability-helper -

的相关更改
User.jsx