Search code examples
javascriptformsreactjsreact-final-form

How to pass null as a field's initial value in react-final-form?


A custom React component I use inside a react-final-form <Field> has a value prop of int?. Its value can either be an integer or null. But when I set a null initial value for this field component's value using the initialValues prop of the <Form> component, react-final-form converts the null to an empty string ''.

I know I can easily work around this by creating a wrapper component that checks for '' and converts it to null, but is there some other cleaner way to fix this? Or is this a library bug?

https://codesandbox.io/s/yq00zxn271

import React from "react";
import { render } from "react-dom";
import { Form, Field } from "react-final-form";

const IntField = (props) => (
  <span>
    <input type="text" value={props.value === null ? 0 : props.value} />
    <pre>
      <b>props.{props.name} === null</b> : {(initialValues[props.name] === null).toString()}
      <br />
      <b>props.value === null</b> : {((isNull) => (<span style={{ color: isNull ? 'green' : 'red' }}>{isNull.toString()}</span>))(props.value === null)}
      <br />
      <b>props: </b>{JSON.stringify(props)}
      <br />
      <b>initialValues: </b>{JSON.stringify(initialValues)}
    </pre>
  </span>
)

const onSubmit = values => {
  console.log('submitted')
}

const initialValues = { someInteger: null };

const App = () => (
    <Form
      initialValues={initialValues}
      onSubmit={onSubmit}
      render={() => (
        <form>
          <label>Some Integer:</label>&nbsp;
          <Field name="someInteger">
            {({ input, meta }) => (
              <IntField {...input} />
            )}
          </Field>
        </form>
      )}
    />
);

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

Solution

  • You can use the <Field> prop allowNull? to turn off this behavior so that null values will be passed as-is to the child component.

    Like this:

    <Field name="someInteger1" allowNull={true}>
      {({ input, meta }) => (
        <IntField {...input} />
      )}
    </Field>
    

    https://codesandbox.io/s/n4rl2j5n04

    (answering my own question as a help for others, since it took me a while to figure out what was going on and how to fix it)