1

The initial state in my component is an array of objects. I am using Redux to fetch another array of objects, as you can see in my below code. I am checking that outCalls is true, if it is I am creating a new array of objects that can be joined with the state.

However in my dependencies array it says I am missing data. If I add it, it creates a mad loop and I get errors. As it currently is, the array of objects doesn't get joined to the state.

useEffect(() => {
        if(outCalls) {
            const transformedOutgoingCalls = outCalls.filter(call => call.contractor._id === props.contractor._id).map(c => ({
                type: 'Outgoing Call',
                contact_person: c.contact_person,
                logged_by: c.created_by.name,
                date: c.time_created,
                link: <> <LinkContainer to={`/outgoing-calls/${c._id}`} className='text-success' style={{ cursor: 'pointer'}}><Eye /></LinkContainer> </>
            }))
            const newData = [...data, transformedOutgoingCalls]
            setData(newData)
        }
    }, [outCalls, props.contractor._id])
4
  • Where do you declare the variable data? Commented May 21, 2021 at 13:39
  • Try to change setData to its callback version, in which you have access to the previous state, and useEffect will no longer complain setData(prevData => [...prevData, tranformedOutgoingCalls]) Commented May 21, 2021 at 13:43
  • when the contractor._id is 1 your state will have a list only with contractor._id 1 info . Now if the contractor._id is 2 does your state have a list with both the contractors info or just contractor 2 info ? Commented May 21, 2021 at 14:07
  • @Shyam Just contractor 2, so it is getting the right data in terms of the contractor id, just duplicating it when i return to the page Commented May 21, 2021 at 15:44

2 Answers 2

2

You can set state in useEffect without declaring data as dependency like below:-

useEffect(() => {
        if(outCalls) {
            const transformedOutgoingCalls = outCalls.filter(call => call.contractor._id === props.contractor._id).map(c => ({
                type: 'Outgoing Call',
                contact_person: c.contact_person,
                logged_by: c.created_by.name,
                date: c.time_created,
                link: <> <LinkContainer to={`/outgoing-calls/${c._id}`} className='text-success' style={{ cursor: 'pointer'}}><Eye /></LinkContainer> </>
            }))
            setData(prevData => [...prevData, ...transformedOutgoingCalls]);
        }
    }, [outCalls, props.contractor._id])

Sign up to request clarification or add additional context in comments.

9 Comments

Perfect, thank you so much! Will accept when it lets me
There is actually a problem happening, if I navigate to a page and go back, it does it again and adds it on top of what was already there. So everything is now there twice. I tried adding another useEffect at the top and put setData([]) but nothing changes
The only thing i see here is having the outCalls as a dependency . since outCalls is an array its reference should not be changing between the re-renders else it will lead to infinite re-render causing maximum depth exceeded error .
where you are getting the outCalls from ? . Is it from redux ?
@Shyam Yes. It says outCalls needs to be a dependency
|
0

Since your state is dependent on outCalls and props.contractor._id . Instead of having a state exclusively you can just have a variable.

// read the data from the store
const outCalls = useSelector(....); 


// since the component re-render when ever there is change in props. Whenever your
// props.contractor._id changes we run this function and get the updated data.

const data = useMemo(() => {
   const transformedOutgoingCalls = outCalls.filter(call => call.contractor._id === props.contractor._id).map(c => ({
        type: 'Outgoing Call',
        contact_person: c.contact_person,
        logged_by: c.created_by.name,
        date: c.time_created,
        link: <> <LinkContainer to={`/outgoing-calls/${c._id}`} className='text-success' style={{ cursor: 'pointer'}}><Eye /></LinkContainer> </>
    }));

    return transformedOutgoingCalls
}, [outCalls, props.contractor._id])

1 Comment

It needs to be in state because there is multiple instances where I have to append to data. So like outcalls, there is more things in the store i need to fetch also and do the same with

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.