How to listen to onChange of the Field component in React-Final-Form?

React-final-form handles this functionality with a tiny external package.

Basically it is an additional component to add inside the form that binds to the element using its name:

<Field name="foo" component="input" type="checkbox" />
<OnChange name="foo">
  {(value, previous) => {
    // do something

The current documentation can be found here:

I haven't used redux-form, but I added a super simple wrapper around the Field component to listen to onChange like this:

const Input = props => {

    const {
    } = props;

    return (
        <Field name={name} validate={validate}>
            {({input, meta}) => {
                return (
                        onChange={(e) => {
                            input.onChange(e); //final-form's onChange
                            if (onChange) { //props.onChange

The idea under change detection is to subscribe to value changes of Field and call your custom onChange handler when value actually changes. I prepared simplified example where you can see it in action. Details are in MyField.js file.

As the result you can use it just as with redux-form:

  onChange={(val, prevVal) => console.log(val, prevVal)}


While the code above still works (check the sandbox version) there is a case when the solutions requires more tweeks around it.

Here is an updated sandbox with an implementation via the hooks. It's based on a useFieldValue hook and OnChange component as a consumer of this hook. But the hook itself can be used separately when you need previous value between re-renders. This solution doesn't rely on of the field.

// useFieldValue.js
import { useEffect, useRef } from "react";
import { useField } from "react-final-form";

const usePrevious = (val) => {
  const ref = useRef(val);

  useEffect(() => {
    ref.current = val;
  }, [val]);

  return ref.current;

const useFieldValue = (name) => {
  const {
    input: { value }
  } = useField(name, { subscription: { value: true } });
  const prevValue = usePrevious(value);

  return [value, prevValue];

export default useFieldValue;

// OnChange.js
import { useEffect } from "react";
import useFieldValue from "./useFieldValue";

export default ({ name, onChange }) => {
  const [value, prevValue] = useFieldValue(name);

  useEffect(() => {
    if (value !== prevValue) {
      onChange(value, prevValue);
  }, [onChange, value, prevValue]);

  return null;

Another nice option is this answer: