0

Im trying to get the use effect to rerender only when the labels property has changed. i want to fetch newest changes in the labels property only when there is a change. My code below:

const usePrevious = (value: any) => {
    const ref = useRef()
    useEffect(() => {
        ref.current = value
    }, value)
    return ref.current
}

const prevLabels = usePrevious(labels)

useEffect(() => {
    if (labels !== prevLabels) {
        fetchUpdatedLabels()
    }
}, [labels, prevLabels])

const fetchUpdatedLabels = async () => {
    await axios
        .get(`/events/${printEvent.id}`)
        .then((response) => {
            const newLabels = response.data.labels
            // filter response to empty array if there are no splits left
            // if is null return empty string
            let fetchedLabels =
                newLabels !== null
                    ? newLabels
                          .toString()
                          .split(',')
                          .filter((label: string) => {
                              return label !== ''
                          }) || ''
                    : ''

            getLabels(fetchedLabels)

            print.updateEvent(printEvent.id, 'value', printEvent.value)
        })
        .catch((err) => {
            console.error(err, 'cant fetch labels from api')
        })
}

it keeps refetching nonstop, how do i achieve this?

1 Answers1

0

This is most likely in part because you are comparing an array with an array using the equivalence operator !==. It can be surprising to people new to JS but if you do this in a JS console:

[1,2,3] === [1,2,3]

It returns false. The reason is that an array is an object and what you are asking is "is the array on the left literally the same as the one on the right" -- as in the same variable. Whereas these are 2 separate array instances that happen to have the same contents. You might wonder why it works then on strings and numbers etc, but that's because those are primitive values and not objects which are instantiated. It's a weird JS gotcha.

There are several ways to compare an array. Try this:

useEffect(() => {
    if (labels.sort().join(',') !== prevLabels.sort().join(',')) {
        fetchUpdatedLabels()
    }
}, [labels, prevLabels])

I'm not sure about your use case here though as when the labels are different, you fetch them, but the only way they can change is to be fetched? Is there something else in the code that changes the labels? If so, won't they get wiped out by the ones from the server now as soon as they change?

Something else is wrong here I think. Where do you set labels into state?

halfer
  • 19,824
  • 17
  • 99
  • 186
adsy
  • 8,531
  • 2
  • 20
  • 31