首页 文章

React Redux:即使mapStateToProps是,也看不到更新

提问于
浏览
2

我的应用程序和商店

使用Redux和ReactJS,我在存储中保留一个对象数组(称为结果),并调度对它进行排序和操作的操作 . 在mapStateToProps中,我返回此结果数组,该结果数组在视图的列表中呈现结果 .

// in Component file
export default class ResultList extends Component {
    constructor(props) {
        super(props);
        this.renderResults = this.renderResults.bind(this);
    }

    renderResults(results) {
        return (
            results.map((result) => {
                return <AnotherComponent />
            })
        );
    }

    render() {
        const { results } = this.props;
        return (
            <div>
                <ul>
                    {this.renderResults(results)}
                </ul>
            </div>
        )

// in Container Component file
const mapStateToProps = (state, ownProps) => {
    console.log('map state is triggered');
    return {
        results: state.results
    };
}

问题

我发现虽然我的mapStateToProps成功触发将道具更新到我的类组件,但出于某种原因 the view only updates on the FIRST time that the results array gets manipulated, but does not update on future updates to the store. (请参阅下面的更新 . 这不完全准确 . )

我已经确定这个问题不是因为我的减速器中的状态发生了变化,这种情况经常发生;我已经确认每次商店更新时都会运行mapStateToProps(如console.log所示) . 问题似乎是从mapStateToProps返回的结果道具和实际呈现结果数组的视图之间的问题,但是我没有看到Redux在幕后做什么的可见性 .

其他人对我所遇到的最接近的问题似乎就是这个,但我不知道这个修复如何或者是否适用于我对存储数组的使用:https://forums.meteor.com/t/the-state-is-correctly-mutated-and-returned-but-view-does-not-rerender/28840/5

任何帮助将不胜感激 . 谢谢 .


更新

我道歉,但必须纠正我上面的陈述,说明在第一次商店中的结果更新后,视图没有进一步的更新 . 通过进一步的测试,我发现这并不完全正确 . The view gets updated only when the results array is sorted according to case 1 of the below sorting function. Cases 2 and 3 are the ones that result in no update to the view. 这可能是/可能不是必要的信息,但结果数组按一个循环中的这3种情况按以下顺序排序:案例1,案例3,案例2 .

// in reducer index.js file
case SORT_RESULTS:
    return {
        ...state,
        results: sortArr(state.results, state.sortType)
    };

// sorting function
function sortArr(arr, sortType) {
    let newArr = [];
    switch (sortType) {
        case '1':
            for (let i = arr.length - 1; i >= 0; i--) {
                newArr.push(arr[i]);
            }
            return newArr;
        case '2':
            newArr = arr;
            newArr.sort((a, b) => {
                return b.num - a.num;
            });
            return newArr;
        case '3':
            newArr = arr;
            newArr.sort((a, b) => {
                let id1 = a.id.toLowerCase();
                let id2 = b.id.toLowerCase();
                if (id1 < id2) {
                    return -1;
                }
                if (id1 > id2) {
                    return 1;
                }
                return 0;
            });
            return newArr;
        default:
            return arr;
    }
}

1 回答

  • 3

    解决方案

    这是罪魁祸首: newArr = arr . 将其更改为 newArr = arr.slice() ,视图将在每种排序中更新 .

    可能的根本原因

    至于为什么这个解决方案有效,我邀请其他人的观点 . 这是我的想法:

    根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

    “slice()方法将数组的一部分的浅表副本返回到从头到尾选择的新数组对象(不包括结束) . ”

    使用 newArr = arr 复制结果数组似乎只复制指针(到数组),这实际上只是内存中的引用 . 如果这个陈述是真的,那么Redux根本不会认为状态已被改变,因为它正在比较完全相同的指针(state.results),即使确认数组本身的实际数据通过排序改变 . 通过 slice() 复制一个全新的数组将涉及一个新的指针和数据,这将被检测为更改为引擎盖下的Redux .

相关问题