1

When I was going through this example https://codesandbox.io/s/miniformik-v2-with-react-hooks-io0me it tells me that there is a missing dependencies and VS Code automatically inserts the dependencies (validate function). And it crashes the app because of it going into endless loop.

If I put the validate function inside the useEffect, it might work but the validate function is used elsewhere. How are you going about this? Do you refactor the whole code that it doesn't have this situation or just ignore the exhaustive deps warning?

Honestly, I would be fine with putting just state.values as deps but rules of hook, exhaustive deps keeps complaining.

  React.useEffect(
    () => {
      if (validate) {
        const errors = validate(state.values);
        dispatch({ type: 'SET_ERRORS', payload: errors });
      }
    },
    [state.values]
  );

And I tried to solve it by calling validate inside useCallback but doesn't seem to work.

  const callbackValidate = useCallback((values) => {
      validate(values);
    },
    []
  );

2
  • Can you show us the validate function ? Commented Aug 17, 2019 at 5:42
  • It is in the codesandbox I forked. Commented Aug 17, 2019 at 6:19

3 Answers 3

3

so your flow looks like this:

You call the useFormik hook like this:

 useFormik({
    validate: values => {
      let errors = {};
      if (values.name !== 'admin') {
        errors.name = 'You are not allowed';
      }
      return errors;
    },
  });

This will creates a new validate function for every render. If you now put your validate function into the useEffect, it will have a different reference on every render, since it is a new function. This will trigger the validate function, which will trigger a new render and it starts again.

You have to either use a static function outside of your component or use useCallback, which will return a memoized function and its reference will only change if its parameters change.

Hope this helps.

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

2 Comments

Thank you for your answer. I tried using useCallback (question updated) but couldn't get it working. Is something wrong with how I used useCallback?
Yes, the [] contain the variables which will trigger a new function. By putting the function into the brackets the useCallback will be called on every render. You have to put into the brackets the variables which will trigger a new run. Since the function will always be the same, just write [].
0

when you use useCallback,you should ensure that the secound arguments you provide keep unchanged. You may create a new validate function for every render

Comments

0

This worked for me by preserving the function using useRef in each render.

  const validateRef = useRef();
  validateRef.current = () => validate(state.values);

  useEffect(() => {
    const errors = validateRef.current();
    dispatch({ type: "SET_ERRORS", payload: errors });
  }, [state.values]);

Comments

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.