derty14
derty14

Reputation: 115

how to fix the problem with rerender in reselect?

It is necessary to sort the data and then filter. When you click on a column header, sorting should occur. On the first click, it should sort in ascending order, on the second click - in descending order, and on the third click, there should be no sorting. Filtering should be performed by the text entered by the user in the field.

When you click on a column header, there is a change in redux, but the data going into the selector does not change. When a field is changed, filtering and sorting occurs.

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>
        )
    }

reducer:

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
});

Upvotes: 1

Views: 106

Answers (1)

derty14
derty14

Reputation: 115

The problem is incorrect data copying.

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

Upvotes: 1

Related Questions