I come across the rendering issue with React State.
The problem is that {state}
in return get value one beat late.
But the console log in handleChange
shows right value.
If the previous value of state is 9, current value of state value is 10 then the console.log({state})
in handleChange
shows 10 and the <span>{state}<span>
in return shows 9.
It looks different from other state async problem.
I can’t understand why this happened.
const [findText, setFindText] = useState(""); const [findCount, setFindCount] = useState(0);
const handleChange = (e) => { let str = e.target.value; setFindText(str); let cnt = 0; doxDocument.map((docx) => { cnt += docx.src.split(findText).length - 1; }); setFindCount(cnt); console.log({findCount}) };
return( <div> <input type="text" value={findText} onChange={handleChange} /> <span>{findCount} found <span> </div> );
Advertisement
Answer
Two problems…
findText
will not have been updated to the new value when you use it insplit()
. Either usestr
instead or calculatefindCount
in a memo or effect hook with a dependency onfindText
.- You’re completely misusing
filter()
. Usereduce()
to calculate a computed sum
const [findText, setFindText] = useState(""); const findCount = useMemo( () => findText ? doxDocument.reduce( (sum, { src }) => sum + src.split(findText).length - 1, 0 ) : 0, [findText, doxDocument] // may not need doxDocument ); return ( <div id="App"> <input type="text" value={findText} onChange={(e) => setFindText(e.target.value)} /> <span>{findCount} found</span> </div> );