React Redux:即使mapStateToProps为

时间:2017-06-27 21:54:31

标签: arrays reactjs sorting redux react-redux

我的申请和存储

将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成功触发将道具更新到我的类组件,由于某种原因视图仅在第一次操作结果数组时更新,但是不会更新商店的未来更新。 (请参阅下面的更新。这不完全准确。)

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

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

非常感谢任何帮助。谢谢。

更新

我道歉,但必须纠正我上面的陈述,说明在第一次商店中的结果更新后,视图没有进一步的更新。通过进一步的测试,我发现这并不完全正确。 仅当根据以下排序函数的案例1对结果数组进行排序时,才会更新视图。情况2和3是导致视图不更新的情况。这可能是/可能不是必要的信息,但结果数组按照以下顺序在循环onClick中按这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 个答案:

答案 0 :(得分:5)

解决方案

这是罪魁祸首:newArr = arr。将其更改为newArr = arr.slice(),视图将在每种类型上更新。

可能的根本原因

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

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

  

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

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