1

Question is very clear as shown in title and I wonder are there any specific differences between these two different functional implementation with useEffect?

Here's an example:

  const lookAtCameraPermission = async (status: CameraPermissionStatus): Promise<void> => {
    switch (status) {
      case 'authorized':
        setIsCameraAllowed(true);
        console.log('Camera permission granted.');
        break;
      case 'not-determined':
      case 'denied':
        setIsCameraAllowed(false);
        console.log('Camera permission denied or not determined');
        await requestCameraPermission();
        break;
      default:
        setIsCameraAllowed(false);
        throw new Error('Unknown camera permission status.');
    }
  };

  useEffect(() => {
    Camera.getCameraPermissionStatus().then(lookAtCameraPermission).catch(console.log);
  }, [lookAtCameraPermission]);

When trying to implement something like this, ESLint says: The 'lookAtCameraPermission' function makes the dependencies of useEffect Hook (at line 66) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of 'lookAtCameraPermission' in its own useCallback() Hook.eslintreact-hooks/exhaustive-deps

I preferred to use useCallback but I couldn't be sure this is the best way to implement this.

Related implementation example: https://github.com/facebook/react/issues/14920

1 Answer 1

1

You can use useRef hook as an alternative way. For example:

const handlerRef = useRef(); 
  
handlerRef.current = async (status: CameraPermissionStatus): Promise<void> => {
    switch (status) {
      case 'authorized':
        setIsCameraAllowed(true);
        console.log('Camera permission granted.');
        break;
      case 'not-determined':
      case 'denied':
        setIsCameraAllowed(false);
        console.log('Camera permission denied or not determined');
        await requestCameraPermission();
        break;
      default:
        setIsCameraAllowed(false);
        throw new Error('Unknown camera permission status.');
    }
}; 

useEffect(() => {
 Camera.getCameraPermissionStatus().then(handlerRef.current).catch(console.log);
}, []);

However, I still refer the way we wrap the handler in useCallback, and pass it as dependencies of useEffect.

  • The first reason is that we don't need to spend a lot of time thinking about what will change to put it in dependencies.
  • Secondly, Make sure useEffect re-run when it's neccessary. If the handler use a variable outside of it, the useEffect hook should re-execute when the variable has changed.

It's terrible when we miss any item in dependencies.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer but still I don't understand. The function is already existed and if I should pass it to the useEffect because re-creation of the function for each render, then I can move the function outside and can keep it static. What are benefits of useCallback or useRef here instead of static definition?
Static definition is ok in this case. But, in case your function render a component, use can not use hooks or fetch data inside of it. For example, how to call setIsCameraAllowed (pass it as arg, curry func?), this is what we trade-off.
It's a good point, thanks. I missed that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.