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:

  1. the component receives new prop value. componentwillreceiveprops called.
  2. inside componentwillreceiveprops first thing happens call setstate. fine... except state won't update until after componentwillreceiveprops 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.

  1. this.ajax() called. inside ajax() axios.get() call. notice here how you're formatting url this.state.val in it. @ point component state has still not updated, you're sending request wrong url.
  2. ajax() finishes running, , componentwillreceiveprops(). sometime after point when statewill 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

Popular posts from this blog

mysql - Dreamhost PyCharm Django Python 3 Launching a Site -

java - Sending SMS with SMSLib and Web Services -

java - How to resolve The method toString() in the type Object is not applicable for the arguments (InputStream) -