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
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.