Search code examples
react-hook-formreact-admin

React-Admin: Access to an ArrayInput element's original value in Edit


I am rendering a custom Input as part of an ArrayInput (via SimpleFormIterator) and the Input needs to know the original value it held before any possible changes by the user.

React Admin's FormDataConsumer used to provide a getSource function to find the "path" to the current element inside a form but it was removed in RA v5 so I can't use that and play directly with react-hook-form state (which feels wrong anyway). The scopedFormData it provides is not useful as it represents the current - not original - value.

Simplified code example:

const MyInput = ({ source, ...rest }) => {
  const origValue = ...;   <-- how?
  return (
    <TextInput source={source} helperText={"Value was: "+origValue} {...rest} />
  );
}

export const MyEdit = () => {
  return (
    <Edit>
      <SimpleForm>
        <ArrayInput source={source} label="Rules">
          <SimpleFormIterator>
            <MyInput source="text" />
          </SimpleFormIterator>
        </ArrayInput>
      </SimpleForm>
    </Edit>
  );
};

I'm sure there's an elegant way to peek into the initial record for the current input?


Solution

  • The getSource equivalent for React Admin v5 is the SourceContext.

    It was not documented in the upgrade guide as it is considered internal API, but it is unlikely to change and we are thinking about documenting it anyways due to popular request.

    So if you want to call getValue on the source of the input inside ArrayInput, you can use the useSourceContext hook to access it.

    const sourceContext = useSourceContext();
    const finalSource = sourceContext.getSource(source);
    const { getValues } = useFormContext();
    const origValue = getValues(finalSource);
    

    You can find a more complete code example here.

    That being said, please note that if your custom input MyInput rerenders, origValue will be updated to the current value of the input in the form, so you may loose the original value.

    What you may need instead is to get the value from the RecordContext (the record is not updated until the Save button is hit).

    const sourceContext = useSourceContext();
    const finalSource = sourceContext.getSource(source);
    const record = useRecordContext();
    const origValue = get(record, finalSource);
    // with get imported from lodash/get
    

    Hope this helps.