shackra
shackra

Reputation: 376

Select with value prop inside of Form.Item won't reflect any change of that value prop

I'm having trouble with antd forms in regard to Select input. I have two Select inputs and I need the second input to "reset" to the first option when the first input changes value.

Edit Select won't obey change of value

I need to keep track of each Select value with React.useState because —in my real code— those values are used to make a request to a backend and re-populate other Select inputs but the first one, and each Select have a different amount of options, thus is desirable that they get "reset" to the first option.

How can I achieve what I'm looking for?

Upvotes: 0

Views: 939

Answers (2)

iamhuynq
iamhuynq

Reputation: 5539

If you add Select into the Form and Form.Item and set a name for Form.Item, the Select is completely controlled by the Form. You need to use the Form's api to control the Select or simply remove the name

import React from "react";
import ReactDOM from "react-dom";
import { Select, Form } from "antd";
import "antd/dist/antd.css";

const fieldA = [{ value: 1, text: "Hello" }, { value: 2, text: "World" }];
const fieldB = [{ value: 1, text: "A" }, { value: 2, text: "B" }];

const App = () => {
  const [myvalues, setMyvalues] = React.useState({ valueA: 1, valueB: 1 });
  const setFieldA = (value: number) => {
    setMyvalues({ valueA: value, valueB: 1 });
    form.setFieldsValue({ valueA: value, valueB: 1 });
  };
  const setFieldB = (value: number) => {
    setMyvalues({ ...myvalues, valueB: value });
    form.setFieldsValue({ ...myvalues, valueB: value });
  };
  const [form] = Form.useForm();
  return (
    <Form layout="vertical" form={form} initialValues={myvalues}>
      <Form.Item name="valueA" label="Field A" shouldUpdate>
        <Select value={myvalues.valueA} onChange={setFieldA}>
          {fieldA.map(field => (
            <Select.Option value={field.value}>{field.text}</Select.Option>
          ))}
        </Select>
      </Form.Item>
      <Form.Item name="valueB" label="Field B" shouldUpdate>
        <Select value={myvalues.valueB} onChange={setFieldB}>
          {fieldB.map(field => (
            <Select.Option value={field.value}>{field.text}</Select.Option>
          ))}
        </Select>
      </Form.Item>
      <div>
        Field A "real" value: {myvalues.valueA}.<br />
        Field B "real" value: {myvalues.valueB}
      </div>
    </Form>
  );
};

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

You can check here CodeSandBox. Hope it helps

Upvotes: 2

keikai
keikai

Reputation: 15186

Since you decide to control the input field with value and onChange,

You don't need the Form name, remove it.

Then set the first hander, check if the value changed to decide whether set the second to default or not.

import React from "react";
import ReactDOM from "react-dom";
import { Select, Form } from "antd";
import "antd/dist/antd.css";

const fieldA = [{ value: 1, text: "Hello" }, { value: 2, text: "World" }];
const fieldB = [{ value: 1, text: "A" }, { value: 2, text: "B" }];

const App = () => {
  const [valueA, setValueA] = React.useState(null);
  const [valueB, setValueB] = React.useState(null);
  const setFieldA = (value: number) => {
    if (valueA !== value) {
      setValueB(null);
    }
    setValueA(value);
  };

  const setFieldB = (value: number) => {
    setValueB(value);
  };

  return (
    <Form layout="vertical">
      <Form.Item label="Field A">
        <Select value={valueA} onChange={setFieldA}>
          {fieldA.map(field => (
            <Select.Option value={field.value}>{field.text}</Select.Option>
          ))}
        </Select>
      </Form.Item>
      <Form.Item label="Field B">
        <Select value={valueB} onChange={setFieldB}>
          {fieldB.map(field => (
            <Select.Option value={field.value}>{field.text}</Select.Option>
          ))}
        </Select>
      </Form.Item>
      <div>
        Field A "real" value: {valueA}
        <br />
        Field B "real" value: {valueB}
      </div>
    </Form>
  );
};

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

Edit Select won't obey change of value

enter image description here

Upvotes: 2

Related Questions