React ref & Formik innerRef - current.values doesn't get updated

Viewed 2597

I'm trying to use Formik in combination with React's useRef hook to create a reference to my form, which I can then access outside of that form. However, no matter what I do, the values in the ref are never updated like I expect them to.

I've created a small example demonstrating the problem.

import React, { useEffect, useRef, useMemo } from "react";
import { render } from "react-dom";
import { Formik } from "formik";

const App = () => {
  const formRef = useRef();

  useEffect(() => {
    console.log("formRef changed", formRef.current);
  }, [formRef]);

  const email = useMemo(() => {
    if (formRef.current) {
      const email = formRef.current.values;
      return email;
    }

    return "<none>";
  }, [formRef.current?.values]); //This dependency array was a test, I tried formRef and formRef.current separately aswell.

  return (
    <div className="app">
      <Formik
        innerRef={(f) => (formRef.current = f)}
        initialValues={{ email: "asdf@test.com" }}
        onSubmit={(values) => {
          console.log(values);
        }}
      >
        {(props) => {
          const {
            values,
            isSubmitting,
            handleChange,
            handleReset,
            handleSubmit
          } = props;
          return (
            <form onSubmit={handleSubmit}>
              <label htmlFor="email" style={{ display: "block" }}>
                Email
              </label>
              <input
                id="email"
                placeholder="Enter your email"
                type="text"
                value={values.email}
                onChange={handleChange}
              />
              <button type="button" className="outline" onClick={handleReset}>
                Reset
              </button>
              <button type="submit" disabled={isSubmitting}>
                Submit
              </button>
            </form>
          );
        }}
      </Formik>
      <span>Entered e-mail: {email}</span>
    </div>
  );
};

render(<App />, document.getElementById("root"));


Unfortunately, I couldn't get it to work with Stack Snippets, so I made a codesandbox instead: https://codesandbox.io/s/formik-example-forked-0osy6?file=/index.js

I originally wanted to do it this way because I need this value somewhere completely unrelated to the form. I considered just using a state variable but this felt like unnecessarily duplicating state, but I might be wrong.

Many thanks!

2 Answers

useRef can't notify, You can't rerender react component. For rerender the page u neeed to use useState for updating your component when the value update .

instead of using const formRef = useRef();
use : const [values, setValues] = useState({});

in Formik replace innerRef={(f) => (formRef.current = f)} with:
innerRef={(formikActions) => (formikActions? setValues(formikActions.values) : setValues({})}

now u can update the useEffect to listen to the values state , and so the changes will always be listened to .

useEffect(() => {
    console.log("values changed", values);
  }, [values]);
Related