Home > OS >  Maintaining multiple user inputs to antd Select in a single useState variable
Maintaining multiple user inputs to antd Select in a single useState variable

Time:11-24

I want to store the information of multiple inputs entered into antd Select components in a single state variable but am having trouble getting the below to work.

This example is solved here for a form but the same solution doesn't seem to work for antd Select component. There are two inputs: a first name and a last name that I want to remember. The below code doesn't work because e doesn't have an attribute called name is what the console tells me. I also tried e.target.name and e.target.value but I get an error that e doesn't have an attribute called a target either. What is the right way to do this?

import React, { useState } from 'react';
import { Select } from 'antd';

const App = () =>{

  const [varState, setVarState] = useState({firstName:'Jack', lastName:'Smith'});
  const firstNameOptions = [ {label:'Jack', value:'Jack'}, {label:'Jill',value:'Jill'}, {label:'Bill',value:'Bill'} ];
  const lastNameOptions = [ {label:'Smith', value:'Smith'}, {label:'Potter',value:'Potter'}, {label:'Bach',value:'Bach'} ];

  const changeState = (e) => {
    setVarState( prevState => ({ ...prevState, [e.name]: e.value}));
    console.log(varState)
  };

  return ( <>
      <div>
        <Select name={'firstName'} defaultValue={'Pick One'} options={firstNameOptions} onChange={changeState}   />
        <Select name={'lastName'} defaultValue={'Pick One'} options={lastNameOptions} onChange={changeState}   />
      </div>
      </>
  );
}

export default App;
  1. At the heart of it, it seems that I don't know how to name the Select components in such a way that their names can be passed on to the onChange handler.
  2. More generally, given a component like antd Select, how can I figure out what the right "name field" is for this component so that it's value can be passed on to an onChange handler? For instance, what in the documentation for select gives this information?

CodePudding user response:

The Select component seems to be sending the value instead of the events object. So, You can just make a closure and pass the name of the select. Also, for consoling you can make use of a useEffect which only consoles when the state has been updated. Otherwise, you could see previous state as state updates are asynchronous. Below is a working solution.

import React, { useEffect, useState } from "react";
import { Select } from "antd";

const App = () => {
  const [varState, setVarState] = useState({
    firstName: "Jack",
    lastName: "Smith"
  });
  const firstNameOptions = [
    { label: "Jack", value: "Jack" },
    { label: "Jill", value: "Jill" },
    { label: "Bill", value: "Bill" }
  ];
  const lastNameOptions = [
    { label: "Smith", value: "Smith" },
    { label: "Potter", value: "Potter" },
    { label: "Bach", value: "Bach" }
  ];

  // for consoling when the state updates
  useEffect(() => {
    console.log(varState);
  }, [varState.firstName, varState.lastName]);

  const changeState = (value, identifier) => {
    // console.log(value, identifier);
    setVarState((prevState) => ({ ...prevState, [identifier]: value }));
  };

  return (
    <>
      <div>
        <Select
          name={"firstName"}
          defaultValue={"Pick One"}
          options={firstNameOptions}
          onChange={(val) => changeState(val, "firstName")}
        />
        <Select
          name={"lastName"}
          defaultValue={"Pick One"}
          options={lastNameOptions}
          onChange={(val) => changeState(val, "lastName")}
        />
      </div>
    </>
  );
};

export default App;

CodePudding user response:

yes, Actually antd doesn't have attribute name for input fields. antdesign directly gives the selected value, we need to do some tweeks to achieve this.

Here is the solution:

import React, { useState } from 'react';
import { Select } from 'antd';

const firstNameOptions = [ {label:'Jack', value:'Jack'}, {label:'Jill',value:'Jill'}, {label:'Bill',value:'Bill'} ];
const lastNameOptions = [ {label:'Smith', value:'Smith'}, {label:'Potter',value:'Potter'}, {label:'Bach',value:'Bach'} ];

const App = () =>{

  const [varState, setVarState] = useState(null);
      
  const changeState = (fieldName) => (value) => {
    setVarState( prevState => ({ ...prevState, [fieldName]: value}));
    console.log(varState)
  };

  return ( <>
      <div>
        <Select defaultValue={'Pick One'} options={firstNameOptions} onChange={changeState('firstName')}   />
        <Select defaultValue={'Pick One'} options={lastNameOptions} onChange={changeState('lastName')}   />
      </div>
      </>
  );
}

export default App;

I hope this helps

  • Related