lobs
lobs

Reputation: 439

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

i try to create functional component on React, Typescript and ant ui. But when i create child component i have warning - "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?". Please tell me where i made mistakes?

CreateCounterpartyComponent:

const CreateCounterpartyComponent: React.FC<FormComponentProps> = props => {
  const GET_ALL = gql`
    query {
      types {
        value: id
        name: full_name
      }
    }
  `;
  const { getFieldDecorator } = props.form;
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log(e);
  };
  const changeHandler = (e:number) => {
    console.log(e)
  }
  const { loading, data } = useQuery(GET_ALL);
  if (loading) return <Loader />;
  return (
    <div>
      <Form onSubmit={handleSubmit}>
        <Form.Item hasFeedback>
          {getFieldDecorator('address', {
            rules: [{ required: true, message: 'Address?' }],
          })(<CustomSeletor items={data.types} width="20%" changeEvent={(e)=>changeHandler(e)}/>)}
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit" className="login-form-button">
            Send
          </Button>
        </Form.Item>
      </Form>
    </div>
  );
};

export const CreateCounterparty = Form.create()(CreateCounterpartyComponent);

CustomSeletor:

const { Option } = Select;

interface IProps {
  items: ISelectorProps[];
  width: string;
  changeEvent(e:number):void;
}

export const CustomSeletor: React.FC<IProps> = ({ items, width, changeEvent }) => {
  const mystyles = {
    width: width,
  };
  const handleChange = (e:number) => {
      changeEvent(e)
  }
  const options = items.map(({ value, name }) => <Option key={value} value={value}>{name}</Option>);
  return (
    <Select style={mystyles} onChange={handleChange}>
      {options}
    </Select>
  );
};

Upvotes: 2

Views: 4362

Answers (1)

Dan
Dan

Reputation: 10548

You're using antd. As specified on this page:

Customized or third-party form controls can be used in Form, too. Controls must follow these conventions:

  • It has a controlled property value or other name which is equal to the value of valuePropName.
  • It has event onChange or an event which name is equal to the value of trigger.

antd requires that CustomSelector be able to receive refs. Function components must be wrapped in React.forwardRef in order to receive refs, otherwise you will get the error you see.

The solution is to wrap CustomSelector in forwardRef:

export const CustomSelector = React.forwardRef(({ items, width, changeEvent }, ref) => {
  const mystyles = {
    width: width,
  };
  const handleChange = (e:number) => {
      changeEvent(e)
  }
  const options = items.map(({ value, name }) => <Option key={value} value={value}>{name}</Option>);
  return (
    <Select ref={ref} style={mystyles} onChange={handleChange}>
      {options}
    </Select>
  );
});

You should ensure that Select conforms to the requirements of antd. Check their docs for that as I don't know them.

Upvotes: 2

Related Questions