javascript - ReactJS: I have a click handler that is skipping the first props method -
import react 'react'; import reactdom 'react-dom'; import axios 'axios'; var mode=[ 'recent', 'alltime']; class header extends react.component { constructor(){ super() } render(){ return <h2>free code camp leader board</h2> } } class leader extends react.component { constructor(props){ super(props) this.state = { users: [], val: props.m } } componentwillreceiveprops(props){ this.setstate({val: props.m}) this.ajax(); } componentwillmount() { this.ajax(); } ajax(){ this.serverrequest = axios.get("https://fcctop100.herokuapp.com/api/fccusers/top/"+this.state.val) .then((result) => { console.log(result.data); var leaders = result.data; this.setstate({ users: leaders }); }); } componentwillunmount() { this.serverrequest.abort(); } render() { console.log(this.state, this.props) return ( <div classname='container'> <div classname="tbl"> <table classname="table"> <thead> <tr> <th>name</th> <th>recent </th> <th>alltime</th> </tr> </thead> <tbody> {this.state.users.map(function(data, index){ return (<tr key={index}><td><img src={data.img} classname="img img-thumbnail" width="50"/>{data.username}</td> <td id='recent'>{data.recent}</td> <td id='alltime'>{data.alltime}</td></tr>) })} </tbody> </table> </div> </div> ) } } class app extends react.component{ constructor() { super(), this.state={val: mode[0]}, this.onclick= this.onclick.bind(this) } onclick() { this.setstate({val: this.state.val === mode[0]? mode[1] : mode[0]}) } render() { return ( <div> <div classname='header'> <header /> <button onclick={this.onclick} >{this.state.val==mode[0]? mode[1] : mode[0]}</button> </div> <div> <leader m={this.state.val} /> </div> </div> ); } } export default app;
for reason app loads properly, on first click of button inside of clicked, nothing; however, works fine on subsequent clicks, aside being out of sync text on button. there wrong use of componentwillreceiveprops method?
the problem how you're doing ajax , managing react state. let's take look:
componentwillreceiveprops(props){ this.setstate({val: props.m}) this.ajax(); } ajax(){ this.serverrequest = axios.get("https://fcctop100.herokuapp.com/api/fccusers/top/"+this.state.val) .then((result) => { console.log(result.data); var leaders = result.data; this.setstate({ users: leaders }); }); }
let's walk through happens here:
- the component receives new prop value.
componentwillreceiveprops
called. - inside
componentwillreceiveprops
first thing happens callsetstate
. fine... exceptstate
won't update until aftercomponentwillreceiveprops
finishes running. the react docs:
setstate() not mutate this.state creates pending state transition. accessing this.state after calling method can potentially return existing value.
so moment nothing - state
remains time being; has outdated value! i'm not sure if it's explicitly documented far know, only reliable place access state
after this.setstate
in render()
function.
this.ajax()
called. insideajax()
axios.get()
call. notice here how you're formatting urlthis.state.val
in it. @ point componentstate
has still not updated, you're sending request wrong url.ajax()
finishes running, ,componentwillreceiveprops()
. sometime after point whenstate
will actually update. but, you've initiated ajax call wrong url, it's late now!
in nutshell: this.setstate
not update state
right away , that's problem. you're seeing result ajax that's "one state" old.
how fix it
it's easy actually. instead of ajax
relying on whatever this.state.val
@ moment called, rewrite accept parameter.
componentwillreceiveprops(props){ this.setstate({val: props.m}) this.ajax(props.m); } // have modify componentwillmount() because should pass parameter // no need access state though - use prop directly componentwillmount() { this.ajax(this.props.val); } // ajax() accept parameter use construct url ajax(value){ this.serverrequest = axios.get("https://fcctop100.herokuapp.com/api/fccusers/top/"+value) .then((result) => { console.log(result.data); var leaders = result.data; this.setstate({ users: leaders }); }); }
other notes
it's weird of taking in changing props
, reason transferring them state
. can use props
directly, , whenever change, use componentwillreceiveprops()
do ajax calls or whatever.
Comments
Post a Comment