Chad D Chad D - 3 months ago 20
React JSX Question

ReactJS why will this state change not render? What am I doing wrong?

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.

Answer

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.

Comments