【问题标题】:how to fix the problem with rerender in reselect?如何解决重新选择中重新渲染的问题?
【发布时间】:2021-03-03 14:23:29
【问题描述】:

需要对数据进行排序,然后过滤。当您单击列标题时,应进行排序。在第一次单击时,它应该按升序排序,在第二次单击时 - 按降序排序,在第三次单击时,应该没有排序。过滤应由用户在字段中输入的文本执行。

当你点击一个列标题时,redux 有变化,但是进入选择器的数据没有变化。当字段发生变化时,就会发生过滤和排序。

AppContainer.js:

import {connect} from "react-redux";
import {FilterAC, PageNumberAC, RowsAC} from "./store/filter";
import {App} from "./App";
import React,{useState} from "react";
import {itemsSelector} from "./selector";
import {RowName} from "./components/RowName";

let MSTP = (state) => ({
    filter: state.filter,
    data: itemsSelector(state),
    allItems: state.data,
    pageNumber: state.pageNumber,
    rows: state.rows,
    sorting:state.sorting

});
let AppHOC =(props) => {
    let [method,setMethod]=useState(3)
    let ChangeSort = (name, method,setMethod) => {
        if (method===3||props.sorting.name!==name){
            setMethod(1);
            method=1
        }else {
            setMethod(method+1);
            method++
        }
        (method === 1)?props.RowsAC(name, "ascending"):method === 2?props.RowsAC(name, "descending"):props.RowsAC("", "");
    };
    let RowNames = props.rows.map((e, i) => {
        return <RowName name={e} method={method} setMethod={setMethod} ChangeSort={ChangeSort} key={i}/>
    })
    return (
        <App FilterAC={props.FilterAC} RowNames={RowNames} filter={props.filter} />
    )
};
export let AppContainer = connect(MSTP, {FilterAC, PageNumberAC, RowsAC})(AppHOC);

selector.js:

 import {createSelector} from "reselect";
    
    let GetItems = (state) => {
        return state.data
    };
    let GETFilter = (state) => {
        return state.filter
    };
    let GETSorting = (state) => {
        return state.sorting
    };
    export let itemsSelector = createSelector(GETFilter, GetItems, GETSorting, (filters, items, sorting) => {
        let sorted = (items, sorting) => {
            items = [...items];
            if (sorting.name === "Name") {
                items.sort((e) => {
                    return e.item
                })
            } else if (sorting.name === "Price") {
                items.sort((a, b) => {
                    return a.price - b.price
                })
            } else if (sorting.name === "Number") {
                items.sort((a, b) => {
                    return a.count - b.count
                })
            }
            if (sorting.method === "descending") {
                return items.reverse()
            }
            return [...items]
        };
        if (filters !== "") {
            return sorted(items, sorting).filter((e) => {
                return e.item.toLowerCase().indexOf(filters.toLowerCase()) > -1
            });
    
        } else {
            return sorted(items, sorting)
        }
    });

RowName.js:

import React from "react";

export let RowName = (props) => {
    let handler = () => {
        props.ChangeSort(props.name, props.method, props.setMethod)
    }
    return (
        <p onClick={handler}>{props.name}</p>
    )
}

FindStroke.js

import React from "react";

    export let FindStroke=(props)=>{
        let handler=(e)=>{
            props.FilterAC(e.target.value)
        };
        return (
            <div>
                <input type="text" value={props.value} onChange={handler}/>
            </div>
        )
    }

减速器:

let data={
    data:[{item:"foo",price:50,count:5},etc]
    filter: "",
    pageNumber: 1,
    rows:['Name','Price','Number'],
    sorting:{name:"",method:""}
};
export let filterReducer = (state = data, action) => {
    switch (action.type) {
        case "filter": {
            let copyState={...state};
            copyState.filter=action.filter;
            copyState.pageNumber=1;
            return {...copyState};
        }
        case "rows":{
            let copyState={...state};
            copyState.sorting.name=action.name;
            copyState.sorting.method=action.method;
            return {...copyState}
        }
        case "pageNumber":{
            return {...state,pageNumber: action.number}
        }
        default :
            return state
    }
};

export let FilterAC = (filter) => ({
    type: "filter",
    filter
});
export let RowsAC = (name,method) => ({
    type: "rows",
    name,
    method
});
export let PageNumberAC = (number) => ({
    type: "pageNumber",
    number
});

【问题讨论】:

    标签: javascript reactjs redux reselect


    【解决方案1】:

    问题是数据复制不正确。

        case "rows":{
           return{...state,sorting {...state.sorting,name:action.name,method:action.method}}
        }
    

    【讨论】:

    • 您永远不应该深度复制整个状态,即使您只更改了 2 个值,它也会重新渲染依赖于状态值的每个组件。您可以改为:return {...state, sorting: {...state.sorting, name:action.name, method:action.method}}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 2020-08-06
    • 1970-01-01
    • 2021-08-22
    • 2016-07-13
    相关资源
    最近更新 更多