fingerprintjs/fingerprintjs-pro-react

neither data, error, or isLoading from useVisitorData is set.

mackopes opened this issue · 4 comments

Hello folks!

I am building a next.js app and I have a code similar to the following example:

"use client";

import { useVisitorData } from "@fingerprintjs/fingerprintjs-pro-react";

export default function FingerprintComponent() {
  const { data, error, isLoading } = useVisitorData({ extendedResult: false });

  if (isLoading) {
    return <LoadingComponent />;
  }

  if (error) {
    return <ErrorComponent />;
  }

  if (data) {
    return <DataComponent fingerprint={data.visitorId} />;
  }

  return null;
}

Of course, the whole app is wrapped in the FpjsProvider.

Would you happen to know when can I expect this code to return null? My expectation is that this should never happen, as the data are either loading, loaded, or an error occured.

However, on some iOS devices, I noticed a behaviour where null is being returned for a couple of seconds and then the data is loaded and the output switches to DataComponent. It behaves as if isLoading was not set to true while the data is loading, but instead the code falls through all branches and returns null until data is present.

What is a good pattern to handle these kind of cases?

Hi @mackopes!

Would you happen to know when can I expect this code to return null? My expectation is that this should never happen, as the data are either loading, loaded, or an error occurred.

This code will always return null initially. You can refer to the hook implementation here. The getData function runs on mount by default, but you can also pass the immediate: false option and call getData explicitly later.

In that case, the data is neither loading nor in error, because getting the data hasn't started. This flow is consistent even if the getData is called automatically after load, which is perhaps not intuitive.

@ilfa Do you think we could do something like this here?

 const [state, setState] = useState<QueryResult<VisitorData<TExtended>>>({
    isLoading: config.immediate ? true : false,
  }) 

What is a good pattern to handle these kind of cases?

For now, if you are using the default behavior (immediate: true), then replacing null with <LoadingComponent /> or similar would probably result in the component behavior you are looking for.

ilfa commented

Yes, @JuroUhlar is right.

We could try this fix, it should improve the behavior.

Thanks a lot for the quick response and clarification! It's much clearer now. I kind of assumed that isLoading is true until we get the data or an error. I'll replace null with a loading component as that's the correct behaviour for our app. Thanks!

No worries, thanks for pointing this out. We have modified the behavior to conform to your original expectations, it really should work like that by default. Try updating to v2.6.3 to test it out. Thanks!