The value of this.state.topText and this.state.bottomText is always one change behind. E.g if I type 1234 in topText’s input box, the value of this.state.topText would be 123. The react docs say to fix asynchronous updates we should use the form of setState() that accepts a function rather than an object. I have done that and the value of setState is still lagging. How do I fix the setState() in handleChange()?
App.js
import React from "react"; import MemeGenerator from "./MemeGenerator" import "./styles.css"; class App extends React.Component { constructor() { super(); this.state = { topText:"", bottomText: "", imgs: [], imgUrl:"" }; this.handleChange=this.handleChange.bind(this) this.handleClick=this.handleClick.bind(this) } handleChange(event) { const {name, value} = event.target this.setState((prevstate) => ({ ...prevstate, [name]: value })); document.getElementById('tt').innerHTML=this.state.topText; document.getElementById('bt').innerHTML=this.state.bottomText; } handleClick(target){ const imgNum=this.state.imgs.length; const randNum=Math.floor(Math.random()*imgNum) this.setState((prevState)=>{ return {imgUrl: prevState.imgs[randNum].url } }) } componentDidMount(){ fetch('https://api.imgflip.com/get_memes') .then((response)=> response.json()) .then((data)=>{ const randImg=data.data.memes this.setState(()=>{ return{imgs: randImg} }) }) } render() { return ( <MemeGenerator handleChange={this.handleChange} handleClick={this.handleClick} topText={this.state.topText} bottomText={this.state.bottomText} imgUrl={this.state.imgUrl} /> ); } } export default App;
MemeGenerator.js
import React from "react" function MemeGenerator(props){ return( <div className="App"> <h1>Meme Generator</h1> <input type="text" name="topText" value={props.topText} onChange={(event)=>props.handleChange(event)} /> <input type="text" value={props.bottomText} name="bottomText" onChange={(event)=>props.handleChange(event)} /> <button onClick={(event)=>props.handleClick(event.target)}>Gen</button> <img src={props.imgUrl} alt="" width="300" /> <p id="tt"></p> <p id="bt"></p> </div> ) } export default MemeGenerator
Advertisement
Answer
setState
accepts a callback as a second param which will be executed right after the state change.
handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }, () => { document.getElementById('tt').innerHTML=this.state.topText; document.getElementById('bt').innerHTML=this.state.bottomText; }); }
Please check the below:
https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296 https://upmostly.com/tutorials/how-to-use-the-setstate-callback-in-react