Search code examples
react-final-form

Should a component adapter wrap just the component or should it also wrap <Field>


Best concept for wrapping react-final-form components

Background

I'm using react-native and will probably start using react-final-form as soon as I have wrapped my head around it. I will build a component library based on react-native-paper.

All examples I've seen on wrapping 3:rd party components for use as react-final-form fields (i.e. <Field>), does not wrap the actual field component. Instead the wrapped component is injected via the component property of the Field component.

If I'm doing all the work wrapping the components, why not go all the way? Since I haven't found any examples of the "complete wrapping", I'm kind of worried that it's not a good idea.

Both solutions seems to work fine, btw. The code below is psuedo:ish.

Only wrapping the component

export default function App() {
  const CheckboxAdapter = ({input: {onChange, value}, meta}) => (
    <Checkbox
      status={value}
      onPress={() => {
        onChange(value === 'checked' ? 'unchecked' : 'checked');
      }}
      errorText={meta.touched ? meta.error : ''}
    />
  );

  return (
    <Form
      ..
      render={({handleSubmit}) => {
        return (
          ..
           <Field
             name="myFieldname"
             component={CheckboxAdapter}
           />
        )
      }
    />
  )
}

Wrapping the component inside of the <Field> component

export default function App() {
  const MyCheckbox = ({name}) => (
    <Field
      name={name}
      component={({input: {onChange, value}, meta, children, ...rest}) => (
        <Checkbox
          status={value}
          onPress={() => {
            onChange(value === 'checked' ? 'unchecked' : 'checked');
          }}
          errorText={meta.touched ? meta.error : ''}
        />
      )};
    />
  );

  return (
    <Form
      ..
      render={({handleSubmit}) => {
        return (
          ..
           <MyCheckbox
             name="myFieldname"
           />
        )
      }
    />
  )
}

Solution

  • Not much interest in this question. I ended up wrapping the <Field>as well. This gives much more readable form code.

    import React from 'react';
    import TextInput from '../components/TextInput';
    import {Field} from 'react-final-form';
    
    const TextInputAdapter = ({input, meta, ...rest}) => {
      const onChangeText = value => {
        input.onChange(value);
      };
    
      return (
        <TextInput
          {...input}
          {...rest}
          onChangeText={onChangeText}
          errorText={meta.touched ? meta.error : ''}
        />
      );
    };
    
    const TextInputField = ({...rest}) => {
      return <Field component={TextInputAdapter} {...rest} />;
    };
    
    export default TextInputField;