6

Here I defined a select component, and I wanted to display it if a condition is true. This select field appears when one of the values ​​of the previous select input is selected. But here is when the new select field (i.e. my select component), and I choose a value from this select, this value is not submitted by my form, and is not present in my data when I do a console log after submitting my form, but the name of the value field is there, but not the value. And i have a warning in my console stating: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of Controller

My Select Component

export const SelectCompanyField = () => {
    // const [page, setPage] = useState(1);
    // const [perPage, setPerPage] = useState(10);
    const { data, error } = useSWR<ServerResponse, any>(companyUrls.base, url => getDataByParams(companyUrls.base));
    console.log("Data", data, "Error", error);
    console.log(data?.entities);


    return (

        <Select

            showSearch
            placeholder="Choisir une compagnie"
            optionFilterProp="children"
            filterOption={(input, option: any) =>
                option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
            }
        >
            {data?.entities.map(d => (
                <option value={d.index} key={d.id}  >
                    {d.name}
                </option>
            ))}

        </Select>


    );
};

The select component to display if the condition is true

<Col md={24} lg={24} sm={24}>


                    {firstOptionValue &&
                        <div className="ant-form-item">
                            <label className="label">Compagnie <span className="text-danger">*</span></label>

                            <Controller

                                as={<SelectCompanyField />}
                                name="company"
                                control={control}
                                defaultValue={""}
                                rules={{ required: false }}

                            {errors.company && "Company is required"}
                        </div>

                    }
                </Col>

The console log of my data submit

{
    "firstName": "Atom",
    "lastName": "Proton",
    "username": "xyz@test.ml",
    "password": "00789",
    "phoneNumber": "44258569",
    "profile": "ADMIN",
    "userType": "B2B_CLIENT",
    "company": ""
}

The company part with the empty quotes, is the part where it should have the value of the field I chose in my select component. I would just like the selected value of the field or the option, appear in my data so that I can submit my form. Thanks

Mohamed Sacko
  • 233
  • 1
  • 2
  • 20

2 Answers2

5

SelectCompanyField needs to be:

export const SelectCompanyField = React.forwardRef(() => {
 ...
});

When rendering using Controllers as prop, it passes a ref prop to the as prop. React sees a ref being passed, but you aren't using a forwardRef component.

In addition to this, then you need to actually use the ref (and props) which you don't appear to be doing now in SelectCompanyField that are being provided by Controller.

The docs will help you out

☝️ Please read the docs, but your SelectCompanyField receives props like this:

export const SelectCompanyField = React.forwardRef(({field,meta}) => {
   const { onChange, onBlur, value, ref } = field

   return <Select onChange={onChange} value={value} .../>
});

It Is your job to add the onChange handler and the value to the Select component you are rendering. I don't know what Select component it is - is it frame a component framework? is it just a regular select? - so I can't tell you how to do it, but the hook form docs are pretty clear.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
  • Hi @Adam, with your suggestion the warning has disappeared, but the value of the selected input is not submitted. – Mohamed Sacko May 13 '21 at 12:50
  • @MohamedSacko - See my update, it's clear in the docs - the `SelectCompanyField` receives the `onChange` handler and the `value` from the form, it is your job to plumb those into your component. – Adam Jenkins May 13 '21 at 13:34
  • My ```Select``` is ```import { Button, Col, Input, Row, Select } from "antd";``` – Mohamed Sacko May 13 '21 at 13:58
  • @MohamedSacko - then look at [the docs](https://ant.design/components/select/) for antd to see how to use the component. It looks like you just need to pass the `onChange` and `value` props directly to the `Select` (see my edit). But I've taken you as far as I can, it's time to start reading some docs instead of my answer. If you try stuff and it doesn't work and you aren't sure why, then please come back and ask for help. – Adam Jenkins May 13 '21 at 14:02
0

For anyone with this problem and a component that you can't use ref (because you haven't created the component can't change it, or it doesn't need a ref prop, or you are using typescript with a generic component and used a different/custom name for the ref prop), you can use the react-hook-mask Controller render prop (https://stackoverflow.com/a/69671594/4850646), instead of as, which allows you to customize which props are passed:

Instead of:

<Controller as={<SelectCompanyField />} ... />

You can use:

<Controller render={({ field: { ref, ...field } }) => <SelectCompanyField {...field} />} ... />
Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61