I am working on a useState example, and I am finding that it doesn't work until the second render. The first time around it holds the default value of 0.
import React, { useState } from "react";
const MyState = () => {
const [age, setage] = useState(0);
function handleClick() {
var enteredAge = document.getElementById("txtAge").value;
if (enteredAge) {
setage(enteredAge);
if (enteredAge > 50) {
document.getElementById("lblResult").innerText = "Wow " age "! You're old, rest up!";
} else {
document.getElementById("lblResult").innerText = "Wow " age "! Young gun!";
}
}
}
return (
<div>
Enter Your Age:
<input type="text" id="txtAge" name="age" />
<button onClick={handleClick}> Check </button>
<label id="lblResult"></label>
</div>
);
};
export default MyState;
If I do something like the following, this works fine on every render. But if I use setState inside the function like I showed above, then the age inside the innerText still holds old value. Why is that, and what the right way to do this?
<label id="lblResult">{age}</label>
CodePudding user response:
You should not mutate the DOM node directly, since react maintains the V-DOM and mutations you are doing to lblresult
will be lost after re-render. The right way is to use the state value and conditionally render the data.
import React, { useState } from 'react';
const MyState = () => {
const [age, setage] = useState(0);
function handleClick() {
var enteredAge = document.getElementById('txtAge').value;
if (enteredAge) {
setage(enteredAge);
}
}
return (
<div>
Enter Your Age:
<input type="text" id="txtAge" name="age" />
<button onClick={handleClick}> Check </button>
<label id="lblResult">
{age > 50
? `"Wow ${age}! You're old, rest up!`
: `Wow ${age}! Young gun!`}
</label>
</div>
);
};
export default MyState;
Update:
As Bjorn mentioned, You could use refs
instead of getElementById
to get the input field value. Ref is a Object with persistent reference between re-render, the current
property of the ref holds the DOM node.
import React, { useState, useRef } from 'react';
const MyState = () => {
const [age, setage] = useState(0);
const inputRef = useRef(null);
function handleClick() {
var enteredAge = inputRef.current.value;
if (enteredAge) {
setage(enteredAge);
}
}
return (
<div>
Enter Your Age:
<input type="text" id="txtAge" name="age" ref={inputRef} />
<button onClick={handleClick}> Check </button>
<label id="lblResult">
{enteredAge > 50
? `"Wow ${age}! You're old, rest up!`
: `Wow ${age}! Young gun!`}
</label>
</div>
);
};
export default MyState;