最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Select value doesnt change the first time I trigger onChange event when using setSate React - Stack Overflow

programmeradmin3浏览0评论

I have a set of select menus and I am trying to change a value when I select an option using onChange={updateValue} event. When I first select an option, the value is not being updated in the select menu. It only changes the second time I try to choose an option. Not sure what I am doing wrong.

Edit: I did some more research (OnChange event using React JS for drop down) and I believe I need the value of the select to be updated as well, using setState. I cant figure out how to do it without having a variable for each value and set the state again.

let selectMenus = [
  {
    id: 'id1',
    name: 'name1',
    label: 'label1',
    value: '0',
    options: [
      {
        text: 'All ages',
        value: '0',
      },
      {
        text: '35 - 37 yrs',
        value: '1',
      },
    ],
    buttonLabel: 'Refresh',
  },
  {
    id: 'id2',
    name: 'name2',
    label: 'label2',
    value: '1',
    options: [
      {
        text: 'All ages',
        value: '0',
      },
      {
        text: '45 - 50 yrs',
        value: '1',
      },
    ],
    buttonLabel: 'Refresh',
  },
];

const [url, setUrl] = useState('http://localhost:5000/selectDropdowns1');

const updateValue = () => {
  setUrl('http://localhost:5000/selectDropdowns2');
};

<form>
  {selectMenus.map((select) => (
    <div key={select.id} className='select-container'>
      <label htmlFor={select.id}>{select.label}</label>
      <select id={select.id} name={select.name} value={select.value} onChange={updateValue}>
        {select.options.map((option) => (
          <option value={option.value} key={uuid()}>
            {option.text}
          </option>
        ))}
      </select>
      <button>{select.buttonLabel}</button>
    </div>
  ))}
</form>;

I have a set of select menus and I am trying to change a value when I select an option using onChange={updateValue} event. When I first select an option, the value is not being updated in the select menu. It only changes the second time I try to choose an option. Not sure what I am doing wrong.

Edit: I did some more research (OnChange event using React JS for drop down) and I believe I need the value of the select to be updated as well, using setState. I cant figure out how to do it without having a variable for each value and set the state again.

let selectMenus = [
  {
    id: 'id1',
    name: 'name1',
    label: 'label1',
    value: '0',
    options: [
      {
        text: 'All ages',
        value: '0',
      },
      {
        text: '35 - 37 yrs',
        value: '1',
      },
    ],
    buttonLabel: 'Refresh',
  },
  {
    id: 'id2',
    name: 'name2',
    label: 'label2',
    value: '1',
    options: [
      {
        text: 'All ages',
        value: '0',
      },
      {
        text: '45 - 50 yrs',
        value: '1',
      },
    ],
    buttonLabel: 'Refresh',
  },
];

const [url, setUrl] = useState('http://localhost:5000/selectDropdowns1');

const updateValue = () => {
  setUrl('http://localhost:5000/selectDropdowns2');
};

<form>
  {selectMenus.map((select) => (
    <div key={select.id} className='select-container'>
      <label htmlFor={select.id}>{select.label}</label>
      <select id={select.id} name={select.name} value={select.value} onChange={updateValue}>
        {select.options.map((option) => (
          <option value={option.value} key={uuid()}>
            {option.text}
          </option>
        ))}
      </select>
      <button>{select.buttonLabel}</button>
    </div>
  ))}
</form>;
Share Improve this question edited Jan 11, 2022 at 15:30 Acdn asked Jan 11, 2022 at 13:03 AcdnAcdn 6383 gold badges14 silver badges26 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

The problem is that when you provide onChange prop to select ponent it bee a controlled ponent.

For more information: React Docs - Forms #controlled ponents

When you dealing with controlled ponents you must provide a value to it and when onChange triggerd it should update that value to work properly. Since you did not provide the full code, I imagine you have an array of select menus and options attached to it.

So in this case every select ponent should have own onChange method and own value to work properly. To achive this we should create another ponent for only Select Options. Like this;

function SelectComponent({ optionList, onSelected }) {
  const [value, setValue] = useState();

  const updateValue = ({ target }) => {
    setValue(target.value);
    if (onSelected) onSelected(target.value);
  };

  return (
    <>
      <label htmlFor={optionList.id}>{optionList.label}</label>
      <select
        id={optionList.id}
        name={optionList.name}
        value={value}
        onChange={updateValue}
      >
        {optionList.options.map((option) => (
          <option value={option.value} key={uuid()}>
            {option.text}
          </option>
        ))}
      </select>
      <button>{optionList.buttonLabel}</button>
    </>
  );
}

This ponent accepts to props; optionList and onSelected

optionList is the list of options to render

onSelected is a method that we call when user select and option

On main ponent, we should change the select section with our select ponent with props optionList and onSelected

  return (
    <div>
      {selectMenus.map((select) => (
        <div key={select.id} className="select-container">
          <SelectComponent optionList={select} onSelected={updateValue} />
        </div>
      ))}
    </div>
  );

So overall code is like this:

import { useState } from "react";
import { v4 as uuid } from "uuid";

export default function App() {
  const [url, setUrl] = useState();

  const updateValue = (value) => {
    setUrl(value);
  };

  const selectMenus = [
    {
      id: 1,
      label: "Menu 1",
      name: "menu1",
      buttonLabel: "Menu 1",
      options: [
        {
          text: "option 1",
          value: "option1"
        },
        {
          text: "option 2",
          value: "option2"
        },
        {
          text: "option 3",
          value: "option3"
        }
      ]
    },
    {
      id: 2,
      label: "Menu 2",
      name: "menu2",
      buttonLabel: "Menu 2",
      options: [
        {
          text: "option 1",
          value: "option1"
        },
        {
          text: "option 2",
          value: "option2"
        },
        {
          text: "option 3",
          value: "option3"
        }
      ]
    },
    {
      id: 3,
      label: "Menu 3",
      name: "menu3",
      buttonLabel: "Menu 3",
      options: [
        {
          text: "option 1",
          value: "option1"
        },
        {
          text: "option 2",
          value: "option2"
        },
        {
          text: "option 3",
          value: "option3"
        }
      ]
    }
  ];

  return (
    <div className="App">
      <h1>URL Value: {url}</h1>
      {selectMenus.map((select) => (
        <div key={select.id} className="select-container">
          <SelectComponent optionList={select} onSelected={updateValue} />
        </div>
      ))}
    </div>
  );
}

function SelectComponent({ optionList, onSelected }) {
  const [value, setValue] = useState();

  const updateValue = ({ target }) => {
    setValue(target.value);
    if (onSelected) onSelected(target.value);
  };

  return (
    <>
      <label htmlFor={optionList.id}>{optionList.label}</label>
      <select
        id={optionList.id}
        name={optionList.name}
        value={value}
        onChange={updateValue}
      >
        {optionList.options.map((option) => (
          <option value={option.value} key={uuid()}>
            {option.text}
          </option>
        ))}
      </select>
      <button>{optionList.buttonLabel}</button>
    </>
  );
}

Working example is overhere codesandbox

发布评论

评论列表(0)

  1. 暂无评论