Home > Blockchain >  React state change not triggering useEffect
React state change not triggering useEffect

Time:06-03

I have a component with the following

const [isOpen, setIsOpen] = useState(false);
     {isOpen && (
                <Drop
                  overflow="unset"
                  align={{ right: "left", top: "bottom", bottom: "bottom" }}
                  style={{ overflowY: "scroll" }}
                  target={targetRef.current}
                  onClickOutside={() => setIsOpen(false)}
                  onEsc={() => setIsOpen(false)}
                >
                  <Calendar
                    date={
                      value
                        ? moment(value)
                            .format()
                            .split("T")[0]
                        : null
                    }
                    onSelect={evt => {
                      onCalendarSelect(evt.toString());
                    }}
                    size="small"
                    {...(calendarPassedProps as CalendarProps)}
                  />
                </Drop>
              )}

useEffect(() => {
  console.log("useEffect ",isOpen)
}, [isOpen])

Where onCalendarSelect is

const onCalendarSelect = (v: string) => {
  console.log(isOpen) //always showing true
  setIsOpen(false)
  const date = moment(v)
    .format()
    .split("T")[0]
    .replaceAll("-", "/");
  try {
    setValue(date);
    if (onChange) {
      onChange(date);
    }
  } catch (e) {
    // Prevent invalid dates
  }
};

Now, when I click outside of the drop , and onCLickOutside is triggered, my isOpen useEffect is triggered, hence closing the calendar.

But whenever I trigger the function OnCalendarSelect which does setIsOpen(false) , nothing changes and the useeffect is not being triggered.

What can the issue be?

CodePudding user response:

1.You are not providing a complete component example so we know if there are conflicts, if there's a different setIsOpen that overwrites the one in this component or any other bugs that might be caused by your logic. 2.You are not specifying the relationship of onCalendarSelect and this component. Are you passing the function as a prop? Are you extracting it from context? Is it defined inside the component? 3. Do you have another setIsOpen in the app that could overwrite the one here?

However. I think you should pass the setIsOpen function to your onCalendarSelect function. As in the example below. If this does not work please provide the full component code and the code of the component where onCalendarSelect is.

const [isOpen, setIsOpen] = useState(false);
     {isOpen && (
                <Drop
                  overflow="unset"
                  align={{ right: "left", top: "bottom", bottom: "bottom" }}
                  style={{ overflowY: "scroll" }}
                  target={targetRef.current}
                  onClickOutside={() => setIsOpen(false)}
                  onEsc={() => setIsOpen(false)}
                >
                  <Calendar
                    date={
                      value
                        ? moment(value)
                            .format()
                            .split("T")[0]
                        : null
                    }
                    onSelect={evt => {
                      onCalendarSelect(evt.toString(), setIsOpen);
                    }}
                    size="small"
                    {...(calendarPassedProps as CalendarProps)}
                  />
                </Drop>
              )}

useEffect(() => {
  console.log("useEffect ",isOpen)
}, [isOpen])


const onCalendarSelect = (v: string, setIsOpen: any) => {
  console.log(isOpen) //always showing true
  setIsOpen(false)
  const date = moment(v)
    .format()
    .split("T")[0]
    .replaceAll("-", "/");
  try {
    setValue(date);
    if (onChange) {
      onChange(date);
    }
  } catch (e) {
    // Prevent invalid dates
  }
};

CodePudding user response:

Fixed by adding a evt.stopPropagation

<Drop
              overflow="unset"
              align={{ right: "left", top: "bottom", bottom: "bottom" }}
              style={{ overflowY: "scroll" }}
              target={targetRef.current}
              onClickOutside={() => setIsOpen(false)}
              onClick={(evt: React.MouseEvent) => {
                evt.stopPropagation();
              }}
            >

CodePudding user response:

Invalid return and render.

Try it

const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    console.log("useEffect ", isOpen);
  }, [isOpen]);

  return(
    <>
             <Drop
               overflow="unset"
               align={{ right: "left", top: "bottom", bottom: "bottom" }}
               style={{ overflowY: "scroll" }}
               target={targetRef.current}
               onClickOutside={() => setIsOpen(false)}
               onEsc={() => setIsOpen(false)}
             >
               <Calendar
                 date={
                   value
                     ? moment(value)
                         .format()
                         .split("T")[0]
                     : null
                 }
                 onSelect={evt => {
                   onCalendarSelect(evt.toString());
                 }}
                 size="small"
                 {...(calendarPassedProps as CalendarProps)}
               />
             </Drop>
    </>
  )
  • Related