React-Admin: How to send input values that have been auto filled from an API call?

Viewed 2337

I have an input 'A' that fetches address data from an API and auto fills inputs 'B' 'C' and 'D' based on that data, but after the inputs have been filled and I try to send that form to my backend, none of those auto filled inputs are sent, just the input 'A' is sent. Furthermore, if i manually edit any of the inputs (remove a char, add a space, change the value) the ones that I edited get sent to my backend.

I'm using a reducer to store the state. The inputs that I'm using are all just normal react-admin TextInput components.

Here's the code:

const AutoFill = () => {
  const [searching, setSearching] = useState(false);
  const [error, setError] = useState(false);
  const [stateData, setStateData] = useReducer(
    (state, newState) => ({ ...state, ...newState }),
    {
      cep: '      -   ',
      address: '',
      number: '',
      neighborhood: '',
      city: '',
      state: '',
    }
  );

  const FormControl = (event) => {
    const { name, value } = event.target;
    setStateData({ [name]: value });
  };

  const SearchControl = (event) => {
    const { name, value } = event.target;
    setStateData({ [name]: value });
    if (value && !value.includes('_')) {
      setSearching(true);
      setStateData({ state: '...' });
      setStateData({ city: '...' });
      setStateData({ neighborhood: '...' });
      setStateData({ address: '...' });
      cep(value.replace('-', '')).then(
        (result) => {
          setSearching(false);
          setError(false);
          setStateData({ state: result.state });
          setStateData({ city: result.city });
          setStateData({ neighborhood: result.neighborhood });
          setStateData({ address: result.street });
        },
        () => {
          setSearching(false);
          setError(true);
          setStateData({ state: '' });
          setStateData({ city: '' });
          setStateData({ neighborhood: '' });
          setStateData({ address: '' });
        }
      );
    }
  };

  return (
    <>
      <TextInput
        source="cep"
        error={error}
        value={stateData.cep}
        onChange={SearchControl}
      />
      <TextInput
        source="address"
        disabled={searching}
        value={stateData.address}
        onChange={FormControl}
      />
      <TextInput
        source="number"
        disabled={searching}
        value={stateData.number}
        onChange={FormControl}
      />
      <TextInput
        source="neighborhood"
        disabled={searching}
        value={stateData.neighborhood}
        onChange={FormControl}
      />
      <TextInput
        source="state"
        disabled={searching}
        value={stateData.state}
        onChange={FormControl}
      />
      <TextInput
        source="city"
        disabled={searching}
        value={stateData.city}
        onChange={FormControl}
      />
    </>
  );
};

export const Create = (props) => {
  return (
    <Create {...props}>
      <SimpleForm>
        <NumberInput label="Value" source="price" />
        <AutoFill />
        <RichTextInput label="Description" source="description" />
      </SimpleForm>
    </Create>
  );
};
2 Answers

You're going to need to use React Final Form's FormState and Form solutions. Will use snippets of my code for example.

1) Grab the form values

    const formState = useFormState();
    const form = useForm();

    const {
        asset_system_parent_id: majorSystem,
        classification,
    } = formState.values;

2) Setup useEffect that will observe changes to a form field:

    useEffect(() => {
        const setFluidEnd = async () => {
          DO SOMETHING!!!!!
        };

        if ('Fluid End Maintenance' === classification) {
            setFluidEnd();
        }
    }, [classification, form, notify]);

3) Use form.change (+ form.batch if you need to update multiple inputs)

    useEffect(() => {
        const setFluidEnd = async () => {
            await requestGetList('asset-systems', 'id', 'ASC', 500, {
                description: 'Fluid End',
                relationship: 'parent',
            })
                .then(res => {
                    form.change('asset_system_parent_id', res.data[0].id);
                })
                .catch(error => {
                    notify(`System Assets not found`, 'warning');
                });
        };

        if ('Fluid End Maintenance' === classification) {
            setFluidEnd();
        }
    }, [classification, form, notify]);

You can read more about the api here: https://final-form.org/docs/final-form/types/FormApi

Please use this code.
-index.js file

import axios from "axios";

export const setInputValue = (data) => {
    return axios.get(`https://www.example.com/profile`)
        .then((response) => {
            return response.data;
        });
};

-component.js

 return setInputValue(value).then(() => {
           this.setState(() => ({
                loading: false
            }));
        });

...
render(){
return (
...
   <input type="text" onClick={e => this.onClick(e)} value={this.state.value}/>
..
)}
...
  • react-admin.php
...
public function setInputValue(value)
    {
        try {
            $user->set(value);
            return response()->json(["result" => "successfully!"]);
        } catch (\Exception $e) {
            return getErrorResponse($e);
        }
    }

Related