Issue
I'm getting data from the server and saving it in 2 different states so one will show all the data received and the other one will show it as pagination.
The array type is:
type ArrayType = {
name:string;
id:number;
link:string;
}
Now the first array has over 200 objects inside of it, while the second array has only 15 objects inside of it.
I'm trying to loop and filter it but it returns the lasts objects + the same last Objects:
interface ComponentState {
total?: ArrayType[];
few?: ArrayType[];
}
const Component = () => {
const isMounted = useRef(true);
const [state, setState] = useState<ComponentState>({});
useEffect(() => {
const updateState = async () => {
const res = await fetch(FetchUrl);
const data = await res.json();
setState((prevState) => ({
...prevState,
total: data,
few: data.slice(0, 10),
}));
};
if (isMounted.current) updateState();
return () => {
isMounted.current = false;
};
}, []);
};
Now When I want to update The state.few I'm trying to do:
const onButtonClick = () => {
setState((prevState) => ({
...prevState,
few: [
...state.few!,
...state.total!.filter((item) =>
state.few!.filter((prevItem) => prevItem !== item)
).slice(0,10),
],
}));
};
console.log(state.few);
return <button onClick={onButtonClick}></button>;
And I keep getting the first 10 items of state.total instead of the next 10 items in the list
Solution
In React you should not store variables that can be calculated from the state in another state.
So what's the information you need to implement a 'load more' button?
- all the list elements
- the index up to which you want to render
These are your state variables. Which items to render can be calculated from those.
So I would implement your component as follows:
const Component = ()=> {
const [items, setItems] = useState([]);
const [showN, setShowN] = useState(10);
// calculate elements to render from state
const toRender = items.slice(0, showN);
useEffect(()=>{
// your isMounted ref does not work. You need to check if the component is mounted before setting the state, not before firing the async function
let stillMounted = true;
const updateState = async () => {
const res = await fetch(FetchUrl);
const data = await res.json();
// check if still mounted
if(!stillMounted) return;
setItems(data);
};
updateState();
// on unmount, this function will be called, preventing a state update on an unmounted component
return ()=>stillMounted = false;
}, []);
// just update the showN state when the button is clicked
const onButtonClick = ()=>{
setShowN(before=>before + 10);
}
// return something
}
Answered By - Taxel
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.