Home > Mobile >  React dropdown list not giving the current selected item
React dropdown list not giving the current selected item

Time:12-12

I'm using React/Nextjs v13, and have a drop down list as shown below:

   const [ selectedLevel, setSelectedLevel]= useState("")

   function handleLvelChange ({target}){
     setSelectedLevel(target.value);  // doesn't change the current value
     console.log(target.value); //--> it gives the correct selected item value, ex. L2
     console.log(selectedLevel); // gives noting
     whatIsTheLevel();
   }

   function whatIsTheLevel(){
     console.log(selectedLevel); // gives noting in the first select
   }

   return (
    <div className="m-3"\>
     <label className="form-label mt-3"\>Level\</label\>
     <select className="form-select" onChange={handleLvelChange}\>
      <option value="L1"\>Level 1 \</option\>
      <option value="L2"\>Level 2\</option\>
      <option value="L3"\>Level 3\</option\>
     </select\>
    </div\>
   )

The issue is when I select an item for the first time, the console.log(selectedLevel) give any empty string, which is the default value for the level, however, when I select an item for the second time, it give the previous selected item's value!!. Even if I forced the code to wait for a second before logging the selectedLevel's value, it will give an empty string as well. I wonder why is that and how to fix it.

CodePudding user response:

I used basic html css and made this dropdown. It works fine. I made it generic though but you can get the idea.

import React from "react";
import "./DropDownInput.css";

const DropDownInput = ({
  name,
  options,
  placeholder,
  onChange,
  selectClassName,
  divClassName,
  selectedValue,
  showPlaceholder = true,
  optionDisabledArr = [],
  required = false,
}) => {
  return (
    <div className={`dropdown ${divClassName}`}>
      <span
        className={`dropdown__arrow ${selectedValue && "dropdown__arrow--up"}`}
      />
      <select
        name={name}
        onChange={(e) => onChange(e.target.value)}
        className={selectClassName}
        selectedValue
        required={required}
      >
        {showPlaceholder && (
          <option disabled selected={!selectedValue ? true : false} value="">
            {placeholder}
          </option>
        )}
        {options.map((option) => (
          <option
            key={option.id || option.value}
            value={option.id || option.value}
            selected={selectedValue === (option.id || option.value)}
            disabled={
              optionDisabledArr.length > 0
                ? optionDisabledArr.indexOf(option.id) === -1
                  ? false
                  : true
                : ""
            }
          >
            {option.status || option.value || option.name}
          </option>
        ))}
      </select>
    </div>
  );
};

export default DropDownInput;

See the below screenshots. I hope it will work try to check the selected part in option tag

FirstImage enter image description here

CodePudding user response:

Your implementation has one issue in React. The call in which you are checking the current value is synchronous while the state updates are asynchronous in React.

import * as React from 'react';
import './style.css';

export default function App() {
  const [selectedLevel, setSelectedLevel] = React.useState('');
  const onSelect = (event) => {
    console.log(event.target.value);
    setSelectedLevel(event.target.value); // doesn't change the current value
  };

  return (
    <div>
      <h1>{selectedLevel}</h1>
      <select onChange={onSelect}>
        <option value="L1">Level 1 \</option>
        <option value="L2">Level 2\</option>
        <option value="L3">Level 3\</option>
      </select>
    </div>
  );
}

Try and run the above code.

Further explaination

function whatIsTheLevel(){
       console.log(selectedLevel); // gives noting in the first selec    
}

This is the function that are assuming will prevent the correct state, by running it in synchronous manner.

  • Related