react-responsive-select icon indicating copy to clipboard operation
react-responsive-select copied to clipboard

onListen wrongly invoked with `isOpen=false`

Open loopmode opened this issue 2 years ago • 2 comments

When you change the selected option in a multiselect scenario, the onListen callback is invoked and claims that isOpen is false, while it should still remain true (The user keeps the overlay visible and changes which options are checked, but he does not close the overlay)

Technically, the user dispatches SET_MULTISELECT_OPTIONS actions, and that action type is not handled in this section: https://github.com/benbowes/react-responsive-select/blob/755f30b947da8d64d7a8c9ea55d93d501c8ce005/src/react-responsive-select.tsx#L84-L89

Thus, the onListen callback is invoked with isOpen=false instead of either not being called at all, or called with isOpen=true.

loopmode avatar Oct 25 '21 12:10 loopmode

See reproducible example https://codesandbox.io/s/react-multiple-select-issue-jcq1e

Open console, change options and observe log output.

loopmode avatar Oct 25 '21 12:10 loopmode

A way to work around the problem, based on this recipe, is to only handle the isOpen change on actions that explicitly change the panel open state, instead of on just any action:

  const prevIsOpen = React.useRef(false);

  const handleSelectStatus = React.useCallback((isOpen, name, action) => {
    if (
      action === 'SET_OPTIONS_PANEL_OPEN' ||
      action.startsWith('SET_OPTIONS_PANEL_CLOSED')
    ) {
      if (isOpen && prevIsOpen.current !== isOpen) {
        setOverlayVisible(isOpen);
        prevIsOpen.current = isOpen;
      } else if (!isOpen && prevIsOpen.current !== isOpen) {
        setOverlayVisible(isOpen);
        prevIsOpen.current = isOpen;
      }
    }
  }, []);

loopmode avatar Oct 25 '21 12:10 loopmode