Home > Software design >  Passing a child component(drop down) to the parent component with React-Hook-Forms: ref is not a pro
Passing a child component(drop down) to the parent component with React-Hook-Forms: ref is not a pro

Time:02-11

I have this drop-down (select) component named Size as a child component and nested useFieldArray in the parent component I am receiving warnings every time I submit it and no values are being displayed in the console. What is happening and how can I fix this?

These are the errors:

Warning: Size: ref is not a prop. Trying to access it will result in undefined being returned. If you need to access the same value within the child component, you should pass it as a different prop.

Field is missing name attribute …

Link to codesandbox: https://codesandbox.io/s/react-hook-form-usefieldarray-nested-arrays-forked-vjwbp?file=/src/Drop_drowns/Size.js

Size.js

import { InputLabel, MenuItem, FormControl, Select } from "@mui/material";

const Size = ({ name, ref, defaultValue }) => {
  return (
    <FormControl fullWidth variant="filled">
      <InputLabel id="Size Label">Size</InputLabel>
      <Select
        labelId="Size"
        id="size"
        name={name}
        label="Product"
        ref={ref}
        defaultValue={defaultValue}
      >
        <MenuItem value="S">Small</MenuItem>
        <MenuItem value="M">Medium</MenuItem>
        <MenuItem value="L">Large</MenuItem>
      </Select>
    </FormControl>
  );
};

export default Size;

Nested Field Array:

import React from "react";
import { useFieldArray } from "react-hook-form";
import Size from "./Drop_drowns/Size";
import { TextField } from "@mui/material";

export default ({ nestIndex, control, register }) => {
  const { fields, remove, append } = useFieldArray({
    control,
    name: `test[${nestIndex}].nestedArray`
  });

  return (
    <div>
      {fields.map((item, k) => {
        return (
          <div key={item.id} style={{ marginLeft: 20 }}>
            <label>Colors:</label>
            <Size
              name={`test[${nestIndex}].nestedArray[${k}].field1`}
              ref={register({ required: true })}
              defaultValue={item.field1}
              style={{ marginRight: "25px" }}
            />
            {/* <input
              name={`test[${nestIndex}].nestedArray[${k}].field1`}
              ref={register({ required: true })}
              defaultValue={item.field1}
              style={{ marginRight: "25px" }}
            /> */}

            <TextField
              name={`test[${nestIndex}].nestedArray[${k}].field2`}
              ref={register()}
              defaultValue={item.field2}
            />

            <TextField
              name={`test[${nestIndex}].nestedArray[${k}].field3`}
              ref={register()}
              defaultValue={item.field3}
            />
            <button type="button" onClick={() => remove(k)}>
              Delete Colors
            </button>
          </div>
        );
      })}

      <button
        type="button"
        onClick={() =>
          append({
            field1: "field1",
            field2: "field2"
          })
        }
      >
        Add Colors
      </button>

      <hr />
    </div>
  );
};

fieldArray:

import React from "react";
import { useFieldArray } from "react-hook-form";
import NestedArray from "./nestedFieldArray";
import { TextField } from "@mui/material";

let renderCount = 0;

export default function Fields({ control, register, setValue, getValues }) {
  const { fields, append, remove, prepends } = useFieldArray({
    control,
    name: "test"
  });

  renderCount  ;

  return (
    <>
      <ul>
        {fields.map((item, index) => {
          return (
            <li key={item.id}>
              <TextField
                name={`test[${index}].name`}
                ref={register()}
                defaultValue={item.name}
              />

              <button type="button" onClick={() => remove(index)}>
                Delete
              </button>
              <NestedArray nestIndex={index} {...{ control, register }} />
            </li>
          );
        })}
      </ul>

      <section>
        <button
          type="button"
          onClick={() => {
            append({ name: "append" });
          }}
        >
          Add product
        </button>

        {/* <button
          type="button"
          onClick={() => {
            setValue("test", [
              ...getValues().test,
              {
                name: "append",
                nestedArray: [{ field1: "append", field2: "append" }]
              }
            ]);
          }}
        >
          update product
        </button> */}
      </section>

      <span className="counter">Render Count: {renderCount}</span>
    </>
  );
}

index.js

import React from "react";
import { useForm } from "react-hook-form";
import FieldArray from "./fieldArray";
import ReactDOM from "react-dom";

import "./styles.css";

const defaultValues = {
  test: [
    {
      product: "",
      nestedArray: [{ field1: "", field2: "", field3: "" }]
    },
    {
      product: "",
      nestedArray: [{ field1: "", field2: "", field3: "" }]
    }
  ]
};

function App() {
  const {
    control,
    register,
    handleSubmit,
    getValues,
    errors,
    reset,
    setValue
  } = useForm({
    defaultValues
  });
  const onSubmit = (data) => console.log("data", data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <h1>Array of Array Fields</h1>
      <p>
        The following example demonstrate the ability of building nested array
        fields.
      </p>

      <FieldArray
        {...{ control, register, defaultValues, getValues, setValue, errors }}
      />

      <button type="button" onClick={() => reset(defaultValues)}>
        Reset
      </button>

      <input type="submit" />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CodePudding user response:

You are attempting to pass a prop called ref to a functional component. You can't pass refs to functional components. Also, what you're trying to pass isn't a ref. See https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element for an example of what I'm talking about. If you rename the prop ref to reference, referral, referenceMaterial, etc, you will get rid of the issue. The following error in your console on the sandbox will let you know this as well.

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Just change your props to a different, more descriptive name and you'll be in business again.

  • Related