React Redux:即使mapStateToProps是

gps*_*ugy 2 arrays sorting reactjs 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
    };
}
Run Code Online (Sandbox Code Playgroud)

问题

我发现,尽管我的mapStateToProps成功触发了将props更新到类组件的操作,但是 由于某种原因,该视图仅在操作结果数组的第一时间更新,而在以后对商店的更新时不更新。(请参阅下面的更新。这并不完全准确。)

我已确保此问题不是由于减速器中的状态突变(通常如此)所致;我已经确认,每次存储更新时,mapStateToProps都会运行(如console.log所示)。问题似乎出在从mapStateToProps返回的结果道具和实际呈现结果数组的视图之间,但是我看不到Redux在后台做什么。

别人不得不与我遇到的最接近的问题似乎是这个,但我不知道此修复程序如何或是否适用于我对存储数组的使用:https : //forums.meteor.com/t/the状态正确地进行了突变并返回了,但是视图没有渲染/ 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

gps*_*ugy 6

解决方案

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

可能的根本原因

至于为什么该解决方案有效,我邀请其他人发表意见。这是我的想法:

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

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

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