1
votes
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

var mode=['recent', 'alltime'];

var Button = React.createClass({
  render(){
    return <input type={this.props.type} onClick=    {this.props.onClick} text={this.props.val}/>;
  }
});

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,
    }
  }

  componentDidMount() {
    var th =this;
    this.serverRequest = axios.get("https://fcctop100.herokuapp.com/api/fccusers/top/"+this.state.val).then(function(result){
      console.log(result.data);
      var leaders = result.data;
      this.setState({
        users: leaders
      });
    }.bind(this));
  }

  componentWillUnmount() {
    this.serverRequest.abort();
  }

  render(){
    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.update= this.update.bind(this),
    this.unmount=this.unmount.bind(this)
  }

  unmount(){
    ReactDOM.unmountComponentAtNode(document.getElementById('board'))
  }

  update(){
    this.unmount();
    this.setState({val: this.state.val ===mode[0]? mode[1] : mode[0]});
  }

  render(){
    return (
      <div>
        <div className='header'>
          <Header />
          <button  onClick={this.update}  >{this.state.val==mode[0]? mode[1] : mode[0]}</button>
        </div>
        <div id="board">
          {this.state.val === mode[0]? <Leader m= {this.state.val} /> : this.state.val ===
            mode[1] ? <Leader m= {this.state.val} /> : null}
        </div>
      </div>
    );
  }
}

export default App;

The questionable part is under class App extends React.Component. I am trying to re-render the Leader Component with the state change in the update method. it changes states, but then does not change the property passed to Leader to rerender.

1
What's the purpose of calling unmount(). Do you have the same behaviour if you just comment that line out?azium
I think the issue is componentDidMount only invoked once, only on the client (not on the server), immediately after the initial rendering occurs. If you move this.state.val to leader render it should update.Martin Dawson
ok thanks, yeah the unmount() function was just an experiment in trying to unmount Leader before steState on the val property. currently its a useless function that needs to be removed, most likely.Chad Denaux
Small tip: if you change the anonymous function callback in the get call to be (result) => {}, then you won't need to call bind(this) at the end since => ("arrow") functions lexically pass this.Matthew Herbst

1 Answers

1
votes

You're not doing anything inside Leader with the prop m after it's initial render. So, it is re-rendering, but its state hasn't changed. Remember that the constructor is only called once, before the initial render. So, if you want Leader to respond to prop changes after the initial render and update its state accordingly, you need to use one of the component lifecycle methods.

I would recommend adding a componentWillReceiveProps lifecycle method to your Leader component. This should do it:

componentWillReceiveProps(nextProps) {
  this.setState({ val: nextProps.m });
}

Any easy way to test what's happening inside your components is to just add a console.log(this.props, this.state); as the first line of the component's render.