I have a textfield which contains text and a button which will then process the text. The Button should not be clickable if the textfield is empty. Therefore I wrote this code:
const [text, setText] = useState("");
const [active, setActive] = useState(false)
function HandleActiveButton(value: string = '') {
setText(value)
if (text.length > 0) {
setActive(true)
console.log(text)
} else {
setActive(false)
console.log(text)
}
}
My textfield and my button:
<TextField
id="outlined-basic"
label="Enter your text to begin"
variant="outlined"
fullWidth
multiline
rows={4}
value={text}
onChange={(e) => HandleActiveButton(e.target.value)}
/>
<LoadingButton variant="contained" disabled={!active} loading={loading} loadingPosition="end" onClick={SendRequest}>Go</LoadingButton>
It kinda works but the problem is that the variable is not updated in time. If I write "ab" the console returns "a" and if I write "xyz" the console returns "xy", etc. This means that the activation and deactivation of the button is not working properly. (e.g. After I paste something I have to type one additional character before the button becomes clickable). Why is this happening? I update the text variable before I check the text length.
CodePudding user response:
You can just change the condition from text.length > 0
to value.length > 0
.
The setText(value)
function is asynchronous and hence your code below runs before the value of state is updated.
If you want to checkout why it's async you can check this link
CodePudding user response:
Two problems. Set state is an asynchronous function, you won't see the update until next render. Active is derived state, you can simply replace the if else with const active=text.length>0
in the component body.
CodePudding user response:
You must use the useEffect
hook to check the last value of state. Let's see what happens.
SetState is an asynchronous operation, so when you run setState, JavaScript compiler doesn't wait for the result and immediately executes the next line. It is possible that the value of the state has not changed yet, so you can not trust the value of state.
The solution is useEffect
hook. This hook get a function and an array. The array is called the dependency array that means the function runs whenever the value of one of the array items changes. So you put the state of inside of that array and choose your next move based on that value.
const [text, setText] = useState("");
const [active, setActive] = useState(false)
function HandleActiveButton(value: string = '') {
setText(value)
}
useEffect(() => {
if (text.length > 0) {
setActive(true)
console.log(text)
} else {
setActive(false)
console.log(text)
}
}, [text]);