1

I want to populate both the array state but projectItems doesn't update in useState and when i put projectItems the component re-renders. so, i am using usecallback but when i put filteredItems and projectItems as dependency array in useCallback and callback in useState, useCallback never runs.

const [filteredItems, setfilteredItems] = useState([]);
const [projectItems, setProjectItems] = useState([]);

const { projects } = props;


const callback = useCallback(() => {
        console.log('callback');
        const projectData = projects.map(i => {
            return (
                {
                    key: '1',
                    projectName: i.project_name,
                    size: i.size,
                    location: i.location,
                    status: `Day ${i.Finished_events_days}/${i.total_days_needed}`,
                    score: `${i.score}/10`,
                    view: <a>View Project</a>,
                    download: <a>Download</a>,
                    feedback: <a>Feedback</a>,
                    audit: <a>Audit</a>
                })
        });

        setProjectItems(prevState => [...prevState, ...projectData]);
        console.log(projectItems);
        setfilteredItems([...projectItems]);
    }, [projectItems, filteredItems]);

    useEffect(() => {

    }, [callback]);
devesh
  • 89
  • 1
  • 8
  • `useEffect(() => { }, [callback]);` - what is it for? And where are you calling the callback? – Kreozot Sep 17 '20 at 06:49
  • I see you are trying to log the updated state from within the same render cycle the state update was enqueued. Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Drew Reese Sep 17 '20 at 06:49
  • useEffect(() => { callback() }, [callback]); – Sabrina Luo Sep 17 '20 at 06:50

2 Answers2

1

Issue

State updates are processed between render cycles, so trying to log or use it will only yield the value from the current render cycle, not what it will be in the next render cycle.

setProjectItems(prevState => [...prevState, ...projectData]);
console.log(projectItems); // <-- current state!
setfilteredItems([...projectItems]); // <-- current state!

Solution

Use an effect hook to "react" to the projectItems state update to trigger a filteredItems update.

...
setProjectItems(prevState => [...prevState, ...projectData]);

...

useEffect(() => {
  console.log(projectItems); // <-- updated state!
  setfilteredItems([...projectItems]); // <-- updated state!
}, [projectItems]);

Notes:

  • Unless callback is actually getting passed to a child component I don't think it's necessary to memoize it.
  • I don't think projectItems should be a dependency since the hook callback function updates it.
  • filteredItems isn't a dependency because it isn't referenced in the hook callback.
Drew Reese
  • 43,833
  • 5
  • 21
  • 43
  • but, the another problem is useCallback never runs when i pass callback as a dependency in useEffect, why? – devesh Sep 17 '20 at 17:05
  • @devesh `useCallback` hook callback will only be invoked when one of the hook's dependencies updates, where the returned memoized callback is used is irrelevant. If the `useCallback` hook has an empty dependency array then it runs only once when the component mounts. From the docs, `useCallback` is useful for passing a stable callback reference to children. From the snippet, granted I may need more context, it doesn't appear `useCallback` is necessary. – Drew Reese Sep 17 '20 at 19:38
  • thanks, i read about it. can you give me resource to understand it in more depth. – devesh Sep 28 '20 at 16:39
  • @devesh Are you referring to `useCallback` hook? Something other than the react docs for hooks, and specifically that hook? – Drew Reese Sep 28 '20 at 16:43
  • i am bot confused why that happend in useeffect. i was asking about resource for hooks apart from official docs. – devesh Sep 28 '20 at 17:07
  • @devesh Sorry, are you asking about the `useEffect` in your original snippet or the `useEffect` in my proposed solution? If yours I can't answer as it's an empty code block so I've no idea what it might've been doing, if mine, then it is running the effect callback when the `projectItems` state is updated, which logs the current state and updates the `filteredItems` state. I don't have any react hook resources memorized other than the official docs, though I do know tons of articles/tutorials exist and can be found via google search. – Drew Reese Sep 28 '20 at 18:12
0

You can use a useEffect method to update the changes to array.

useEffect(() => {
  setfilteredItems([...projectItems]);
}, [projectItems]);
Nazeer
  • 373
  • 4
  • 16