1

I have a button that sends a prefetch request using graphQL Apollo Client when a user hovers it.

The issue is the onClick event is blocked for a few ms. Can someone please explain why seperate events are clashing like this. I can't think of any reason why my onclick event is not firing while the request is in flight as its asynchronous.

<div
   role="button"
   key={shortId()}
   onMouseEnter={prefetch(value.value)}
   onClick={onToggle(id, value.value)}
   className="FilterGroup__item"
>
   {renderWidget({value, selected})}
    <span className="FilterGroup__item__count">{value.count}</span>
</div>

The function returned by prefetch is:

    const [searchPrefetch] = useLazyQuery(searchQuery, {
        returnPartialData: true
    });

    const sendSearchPrefetch = (additionalParameters?: IAdditionalSearchParameters) => {
        searchPrefetch({
            variables: getRequestParameters(additionalParameters)
        });
    };

const handlePrefetch = useCallback(
        debounce(async (additionalFacets?: IAdditionalSearchParameters) => {
            sendSearchPrefetch(additionalFacets);
        }, SEARCH_DEBOUNCE_TIMER_MS),
        []
    );

  const prefetch = (filter: string) => (value: string) => () => {
        handlePrefetch({filters: {[filter]: value}});
    };
rnmalone
  • 1,020
  • 13
  • 25
  • 1
    chrome is single thread in terms of performing tasks like handling event and sending request – Guichi Jun 01 '20 at 10:00
  • What does `prefetch` do besides I/O? Is the response large? – Davin Tryon Jun 01 '20 at 10:01
  • How can we guess without any concrete code? [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) – Dennis Vash Jun 01 '20 at 10:02
  • how do you know it is blocked? You click and no reaction? I tried - even very fast enter mouse and immidiately click - and click handler works every time – Dmitry Reutov Jun 01 '20 at 10:05
  • `prefetch(value.value)` returns `(value: string) => () => { handlePrefetch({filters: {[filter]: value}}); }`, the params should be a `Event` rather than a `string` – Guichi Jun 01 '20 at 10:15

2 Answers2

0

Your click is fired on load

Your click and prefetch functions are fired when the component is loaded. If these functions do not return functions to be fired on click and mouse enter you need to wrap them in another function.

<div
   role="button"
   key={shortId()}
   onMouseEnter={() => prefetch(value.value)}
   onClick={() => onToggle(id, value.value)}
   className="FilterGroup__item"
>
   {renderWidget({value, selected})}
    <span className="FilterGroup__item__count">{value.count}</span>
</div>
Joe Lloyd
  • 19,471
  • 7
  • 53
  • 81
0

This is similar issue to this post. It is not good idea to bind handlers to both the click and mouseenter. So, I would suggest you to update the state instead of handling events. After we get the updated state we can call the handler. Here's a pseudo code to demonstrate that:

const [prefetch, setPrefetch] = useState('')
const [toggle, setToggle] = useState({})

onMouseEnter={setPrefetch(value)}
onClick={setToggle({id,value})}

useEffect(() => { // you may use memoized effect
  if (prefetch) {
    prefetchFunc(prefetch)
  }
  if (toggle) { // you may check additional detail
    toggleFunc(toggle)
  }
}, [prefetch, toggle])
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231