Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.7k views
in Technique[技术] by (71.8m points)

javascript - useSelector, and properly switching slices of data to avoid excessive slow downs

I have a list of objects - each with various properties... the list is about 4000 long.

there is a reason to filter and show a subsection of the slice based on a property of these objects... for example... selecting all of them that have the 'paid' bool set to true, or 'rush' bool.

this is my current code.

import {selectJobs,
    selectCompleteJobs,
    selectUncompleteJobs, 
    selectUnpaidJobs} from "../../slices/jobCardSlice";


// inside the component
const [selectors, setSelectors] = useState([selectUncompleteJobs,selectJobs,selectCompleteJobs,selectUnpaidJobs]); // an array of selectors
const found = selectors.find(x=>x===props.selector); //initial selector choosed
const [chosenSelector, setChosenSelector] = useState(selectors.indexOf(found)||0); //a number 
const jobs = useSelector(selectors[chosenSelector]); // the slice
const selectControls = (
    <select className="selectControls"  onChange={(e)=>{
    setChosenSelector(e.target.value);
}}>{selectors.map((x,i)=><option value = {i}>{x.name}</option>)}
    </select>
); // the thing that changes the slice a select element that selects a selector


var jobscards = jobs.map(jobDatat=>(<JobCard key={jobDatat.id} props={jobDatat} />));

// then it renders a box with the selector in the head - and a list of jobcards in the body (boxes have a head/title area, and a body/list area);

and here are the selectors, they are pretty basic.

export const selectJobs = (state) =>{
     return state.jobs;
}
export const selectNoData = (state)=>{
    return state.jobs.filter(x=>x.data===1);
}
export const selectCompleteJobs = (state) =>{
    return state.jobs.filter(x=>x.JobStatus === "COMPLETE");
}
export const selectUncompleteJobs = (state) =>{
    return state.jobs.filter(x=>x.JobStatus !== "COMPLETE");
}
export const selectUnpaidJobs = (state) =>{
    return state.jobs.filter(x=>x.paidStatus!== "PAID");
}

switching between small slices is just barely fast enough... however, if I change to a large slice - it takes more than 15 seconds to load in.

is there a better way to handle filtering of a selector? this is literally just the first thing that came to mind - it technically works but is no where close to production ready due to speed.

how do you handle filtering long lists? (also - the initial load in with all fresh data from the server: that first render is maybe one second - so I think there is a pattern that can be that fast...)

I'm new to react - and I haven't found anything about a good way of handling this yet.

EDIT: i have made the following changes to the slice.

//instead of the old selectors - they are now:


export const selectNoData = createSelector(
    //input selector all jobs
    selectJobs,
    jobs=>jobs.filter(x=>x.dataRecieved==1)

)

export const selectUnpaidJobs = createSelector(
    //input selector all jobs
    selectJobs,
    jobs=>jobs.filter(x=>x.hasBeenPaid !== "PAID")

)
export const selectUncompleteJobs = createSelector(
    //input selector all jobs
    selectJobs,
    jobs=>jobs.filter(j=>j.JobCompleted  !==  "COMPLETE")

)

export const selectCompleteJobs = createSelector(
    //input selector all jobs
    selectJobs,
    jobs=>jobs.filter(j=>j.JobCompleted === "COMPLETE")

)


this does improve performance down to 7 seconds instead of 15.

I'm still looking for further optimization - but that was a big step!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The first issue here is that all of your selectors are always returning a new reference, by calling state.jobs.filter(). That means that these components will be forced to re-render if other actions are dispatched, even if this data didn't actually change.

So, a key first step here is to update these selectors to be "memoized" so that they only recalculate the filtered lists if the input status changes.

See these posts for details:

That doesn't help the list itself render faster, but it will help avoid unnecessary re-renders.

Also, be sure that you're applying appropriate key values to each list item, so that React can keep the list item components alive and reuse the contents. It does look like you're doing that atm, but never hurts to double-check.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...