jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.71k stars 2.77k forks source link

FieldArray Render/Access Specific Index Only #3868

Open aress31 opened 10 months ago

aress31 commented 10 months ago

I'm not familiar with an efficient and user-friendly method to selectively render a specific index using the <FieldArray> component. Please refer to the provided code snippet for more details:

const Form = ({ currentIndex, fields, formik }) => {
  // --- SNIP ---

  return (
    <FormikProvider value={formik}>
      <FormkiForm>
        <FieldArray
          name="rows"
          render={() =>
            renderFormControls(currentIndex, formik, fields, options, loading)
          }
        />
      </FormkiForm>
    </FormikProvider>
  );
};
const renderFormControls = (currentIndex, formik, fields) => {
  return formik.values.rows.map((row, index) =>
    Object.keys(row).map((key) => {
      // --- SNIP ---

      return (
        <FormControl
          key={`${name}-${index}-formControl`}
          fullWidth
          margin="normal"
          variant="standard"
        >
          <FormLabel htmlFor={`${name}-field`}>{fieldName}</FormLabel>
          <FastField
            id={`${name}-field`}
            aria-describedby={`${name}-helper-text`}
            name={`rows.${index}.${name}`}
            render={({ field }) => render(field, params)}
          />
          <ErrorMessage
            id={`${name}-helper-text`}
            name={`rows.${index}.${name}`}
            component={FormHelperText}
            error
          />
        </FormControl>
      );
    })
  );
};

In this example, my requirement is to render a particular index (currentIndex) or form from the rows specification. However, I have to either manually map the entire rows or access the formik.values[currentIndex] in a non-ideal way.

Introducing an option within the render method to provide access and enable manipulation of a specific index or form would be highly beneficial.

Note: It does not seem possible to directly access the rows object like:

const renderFormControls = (currentIndex, formik, fields) => {
  console.log("test", `rows.${currentIndex}`);
  return;
}

EDIT 1: So that is the closest solution I found to this, any suggestions would be appreciated:

const renderFormControls = (
  fieldArrayProps,
  currentIndex,
  fields
) => {
  const { form } = fieldArrayProps;
  const currentRow = form.values.rows[currentIndex];

  return Object.keys(currentRow).map((key) => {
    // --- SNIP ---

    return (
      <FormControl
        key={`${name}-${currentIndex}-formControl`}
        fullWidth
        margin="normal"
        variant="standard"
      >
        <FormLabel htmlFor={`${name}-field`}>{fieldName}</FormLabel>
        <FastField
          id={`${name}-field`}
          aria-describedby={`${name}-helper-text`}
          name={`rows.${currentIndex}.${name}`}
          render={({ field }) => render(field, params)}
        />
        <ErrorMessage
          id={`${name}-helper-text`}
          name={`rows.${currentIndex}.${name}`}
          component={FormHelperText}
          error
        />
      </FormControl>
    );
  });
};

const Form = ({ currentIndex, fields, formik }) => {
  // --- SNIP ---

  return (
    <FormikProvider value={formik}>
      <FormkiForm>
        <FieldArray
          name="rows"
          render={(fieldArrayProps) =>
            renderFormControls(
              fieldArrayProps,
              currentIndex,
              fields
            )
          }
        />
      </FormkiForm>
    </FormikProvider>
  );
};