Javascript 反应状态不变

Javascript 反应状态不变,javascript,reactjs,Javascript,Reactjs,我正在处理这个FreeCodeCamp排行榜表格,当点击突出显示的表格标题时,应用程序会调用此url最近的或此url所有时间的,从而在过去30天的或所有时间的最高分露营者之间进行排序 我在这里的问题是,我必须点击两次,以获得所需的结果。在camperleadboard组件handleSort功能中,当我console.log时,状态在单击两次后才会改变 点击一下 handleSort = (sort) => { console.log(sort); // alltime cons

我正在处理这个FreeCodeCamp排行榜表格,当点击突出显示的表格标题时,应用程序会调用此url最近的或此url所有时间的,从而在过去30天的所有时间的最高分露营者之间进行排序

我在这里的问题是,我必须点击两次,以获得所需的结果。在
camperleadboard
组件
handleSort
功能中,当我
console.log
时,状态在单击两次后才会改变

点击一下

handleSort = (sort) => {
  console.log(sort);  // alltime
  console.log(this.state.sort)  //recent
  this.setState({ sort: sort });
  console.log(this.state.sort)  //recent
  this.getData();
};
点击两次

handleSort = (sort) => {
  console.log(sort);  // alltime
  console.log(this.state.sort)  //alltime
  this.setState({ sort: sort });
  console.log(this.state.sort)  //alltime
  this.getData();
};
这是完整的代码,下面是完整的代码

/**
  Table body component
*/
class Table extends React.Component {
  handleSort = (e, sort) => {
    this.props.handleSort(sort);
  };

  renderCampers = (key, count) => {
    const camper = this.props.campers[key];
    return(
      <tr key={key}>
        <td>{count}</td>
        <td>
          <a href={`https://www.freecodecamp.com/${camper.username}`} target='_blank'>
            <img src={camper.img} />
            {camper.username}
          </a>
        </td>
        <td className='center'>{camper.recent}</td>
        <td className='center'>{camper.alltime}</td>
      </tr>
    )
  };

  render() {
    let count = 0;
    return (
      <div>
        <table>
          <caption>Leaderboard</caption>
          <tr>
            <th>#</th>
            <th>Camper Name</th>
            <th onClick={(e) => this.handleSort(e, 'recent')}><a href='javascript:void(0)'>Points in the past 30 days</a></th>
            <th onClick={(e) => this.handleSort(e, 'alltime')}><a href='javascript:void(0)'>All time points</a></th>
          </tr>
          {Object.keys(this.props.campers).map(key => {
            count++;
            return this.renderCampers(key, count);
          })}
        </table>
      </div>
    );
  }
}

/**
  Container
*/
class CamperLeaderboard extends React.Component {
  state = {
    campers: [],
    sort: 'recent'
  };

  getData() {
    let url = `https://fcctop100.herokuapp.com/api/fccusers/top/${this.state.sort}`
    const self = this;
    axios.get(url)
      .then(function (response) {
        self.setState({ campers: response.data });
        //console.log(self.state.campers);
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  componentWillMount() {
    this.getData();
  }

  handleSort = (sort) => {
    this.setState({ sort: sort });
    this.getData();
  };

  render() {
    return (
      <div>
        <p>Click links in table header to sort</p>
        <Table campers={this.state.campers} 
              handleSort={this.handleSort} />
      </div>
    );
  }
}

ReactDOM.render(<CamperLeaderboard />, document.getElementById('app'));

/*
To get the top 100 campers for the last 30 days: https://fcctop100.herokuapp.com/api/fccusers/top/recent.
To get the top 100 campers of all time: https://fcctop100.herokuapp.com/api/fccusers/top/alltime.
*/
/**
表体组件
*/
类表扩展了React.Component{
handleSort=(e,排序)=>{
this.props.handleSort(排序);
};
renderCampers=(键,计数)=>{
const camper=this.props.camper[key];
返回(
{count}
{camper.recently}
{camper.alltime}
)
};
render(){
让计数=0;
返回(
排行榜
#
露营者姓名
this.handleSort(e,'最近')}>
this.handleSort(e,'alltime')}>
{Object.keys(this.props.campers).map(key=>{
计数++;
返回此.renderCampers(键,计数);
})}
);
}
}
/**
容器
*/
类CamperReadBoard扩展了React.Component{
状态={
露营者:[],
排序:“最近的”
};
getData(){
让url=`https://fcctop100.herokuapp.com/api/fccusers/top/${this.state.sort}`
const self=这个;
获取(url)
.然后(功能(响应){
self.setState({campers:response.data});
//控制台日志(self.state.campers);
})
.catch(函数(错误){
console.log(错误);
});
}
组件willmount(){
这是getData();
}
handleSort=(排序)=>{
this.setState({sort:sort});
这是getData();
};
render(){
返回(
单击表标题中的链接进行排序

); } } ReactDOM.render(,document.getElementById('app')); /* 要获得过去30天的前100名露营者:https://fcctop100.herokuapp.com/api/fccusers/top/recent. 要获得有史以来的前100名露营者:https://fcctop100.herokuapp.com/api/fccusers/top/alltime. */
我相信@finalfreq的解释是正确的,这就是解决问题的方法

更新CamperLeadboard类的handleSort方法,如下所示:

handleSort = (sort) => {
  this.setState({ sort: sort });
  // You don't need to read sort from state. Just pass it :)
  this.getData(sort);
}

我相信@finalfreq的解释是正确的,这就是解决方法

更新CamperLeadboard类的handleSort方法,如下所示:

handleSort = (sort) => {
  this.setState({ sort: sort });
  // You don't need to read sort from state. Just pass it :)
  this.getData(sort);
}

UI是否显示排序仅在第二次之后进行?在第一个示例中,您的console.log在设置状态之后几乎总是不显示更新状态,因为
this.setState
是异步的,这意味着它将进入事件队列并最终被更新。consoleLog仍将显示以前的状态,因为它发生在实际状态更新之前。但是,如果您的UI在设置状态后没有改变,那么还会发生其他事情。是的,UI仅在我第二次单击任一标题后显示排序UI是否仅在第二次单击后显示排序?在第一个示例中,您的console.log在设置状态之后几乎总是不显示更新状态,因为
this.setState
是异步的,这意味着它将进入事件队列并最终被更新。consoleLog仍将显示以前的状态,因为它发生在实际状态更新之前。但是,如果您的UI在设置状态后没有改变,那么其他事情也会发生。是的,只有在我第二次单击其中一个标题时,UI才会显示排序听起来是正确的,您不能期望
setstate
同时工作,文档说
setstate()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,调用可能会被批处理以提高性能。
@R.HalukÖngöR这对我来说是一个“duh”时刻,你的答案很好。@JuanMendes阅读你的链接问题,我也可以这样做,并且效果很好
this.setState({sort},()=>this.getData(this.state.sort))
听起来很正确,你不能期望
setState
在同一轮中工作,文档说
setState()不会立即改变这个.state,而是创建一个挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState调用的同步操作,调用可能会被批处理以提高性能。
@R.HalukÖngöR这对我来说是一个“duh”时刻,你的答案很好。@JuanMendes阅读你的链接问题,我也可以这样做,并且效果很好
this.setState({sort},()=>this.getData(this.state.sort))