DEV Community

SharkAttack86
SharkAttack86

Posted on

React Redux and data updates

Hi everyone

I'm pretty new to React. Although i'm going fine with simple projects, there is now an issue with a complex one. I'm using Redux, with Redux Thunk and some custom hooks.

I have this hook, inside a custom hook

useEffect(() => {
        if (environment.dateStart) {
            if (environment.dateEnd) {
                //props.onUpdateDaysConfig([])
                autoClick(environment.dateStart)
                autoClick(environment.dateEnd)
            } else {
                autoClick(environment.dateStart)
            }
        }
    }, [props.daysConfig.length]);

const autoClick = dateString => {
        const sDate = new Date(dateString);
        const q = props.daysConfig.filter(day => day.day === sDate.getDate() && day.month === sDate.getMonth() + 1 && day.year === sDate.getFullYear());
        if (q.length > 0) {
            onDaySelect(q[0])
        }
    }
Enter fullscreen mode Exit fullscreen mode

props.daysConfig is a state from a Redux store, holding an array of objects with a structure like the following (pseudo code):

  • day (int)
  • month (int)
  • year (int)
  • classes (string[])
  • data (object/any)

onDaySelect is defined this way:

const onDaySelect = data => {
        if (JSON.stringify(data.data) === '{}') {
            handleClickOutsideRates(data)
        } else {
            handleClickInRates(data)
        }
    }
Enter fullscreen mode Exit fullscreen mode

where handleClickOutsideRates and handleClickInsideRates reside on another custom hook; they perform calculations and then trigger some Redux updates. Both of these depend on this, defined on the same hook and available to both:

const alreadySelectedDays = props.daysConfig.filter(d => d.classes.indexOf(constants.selectedClass) > -1);
Enter fullscreen mode Exit fullscreen mode

(constants is an import from another file, defining a set of strings).
This array's length determines what handleClickOutsideRates and handleClickInsideRates will do.

This looks where things break up. If i call onDaySelect from a click, it works just as i expect, in every situation. If i do the same from that useEffect, only the first one works correctly; then the second one is tricked, because alreadySelectedDays is still evaluated as an empty array, no matter what. It's like they get executed at the same moment, or maybe the second one starts before the first gets completed. Anyways, it is clear that i'm missing something about hooks, or maybe Redux itself.

I'm certainly going to move all of that logic to the store, but i would like to know how things are working. Could anyone explain me why is this happening? Thank you.

EDIT: i was able to achieve the desired result this way:

const freeForSecond = useRef(false)
useEffect(() => {
        if (environment.dateStart) {
            autoClick(environment.dateStart)
        }
        return () => {
            freeForSecond.current = true
        };
}, [props.daysConfig.length]);

useEffect(() => {
        if (environment.dateEnd) {
            if (freeForSecond.current)
            autoClick(environment.dateEnd)
        }
}, [freeForSecond.current])

Enter fullscreen mode Exit fullscreen mode

This ensures the second autoClick being called after, granting it to work.
I don't like it. I feel like i'm misusing the returned callback, since i'm doing no cleaning operations in there. Plus, although i forced it to work, i still don't know why it didn't work the way it was.

Top comments (3)

Collapse
 
lexiebkm profile image
Alexander B.K.

I think we should try Redux Toolkit Query (RTKQ) as introduced in Reedux tutorial : redux.js.org/tutorials/essentials/...
which is covered more detail in its doc : redux-toolkit.js.org/rtk-query/ove... and subsequent chapters of the doc.

Collapse
 
majidmade profile image
Majid Razvi

this sounds like either a stale closure or an inaccurate dependency array -- im happy to review a runnable sample if that's helpful

Collapse
 
sharkattack86 profile image
SharkAttack86

Thanks for your reply. I'm sure that dependency array is no good at all. I'll later share a sample so you can review it