点击2

时间:2016-12-01 23:30:02

标签: javascript reactjs

我在" Camper的排行榜"来自FreeCodeCamp的挑战。所以我必须实施这样的事情:"我可以在列表中按照他们在过去30天内获得的布朗尼点数和多少布朗尼点来切换他们已经获得了总数。"
 我将onclick处理程序添加到列表的标题单元格中,但是在对元素进行两次单击而不是一次单击后,它会更改视图。简而言之:
_handlerAll()和_handler30()在连续两次点击后执行,而不是一次。 这是代码:



"use strict";
class TableBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            sortAllTime: true
        };
    }

    loadCampersFromServer() {
        let templateURL = 'https://fcctop100.herokuapp.com/api/fccusers/top/';
        let url = (this.state.sortAllTime) ? (templateURL + 'alltime') : (templateURL + 'recent');
        fetch(url)
            .then(
                (response) => {
                    if (response.status !== 200) {
                        console.log('Looks like there was a problem. Status Code: ${response.status}');
                        return;
                    }
                    response.json().then((data) => {
                        this.setState({data: data});

                    })
                }
            )
            .catch(function (err) {
                console.log('Fetch Error :-S', err);
            });
    }

    _handlerAll() {
        this.setState({sortAllTime: true});
        this.loadCampersFromServer();
        console.log('all');
    }

    _handler30() {
        this.setState({sortAllTime: false});
        this.loadCampersFromServer();
        console.log('notAll');
    }

    componentDidMount() {
        this.loadCampersFromServer();
    }

    render() {
        return <CampersList _data={this.state.data}
        _handlerAll={this._handlerAll.bind(this)} _handler30={this._handler30.bind(this)}/>;
    }
}

class CampersList extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        let campersNodes = this.props._data.map((element, index) => {
            return (
                <Camper user={element} index={index}/>

            );
        });

        return (
            <table>
                <tr>
                    <th>#</th>
                    <th>Camper's Name</th>
                    <th onClick={this.props._handler30}>Points in past 30 days</th>
                    <th onClick={this.props._handlerAll}>All time points</th>
                </tr>
                {campersNodes}
            </table>
        )
    }
}

class Camper extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <tr>
                <td>{this.props.index + 1}</td>
                <td>
                    <img src={this.props.user.img} alt="logo"/>
                    <span>{this.props.user.username}</span>
                </td>
                <td>{this.props.user.recent}</td>
                <td>{this.props.user.alltime}</td>
            </tr>
        )
    }
}

ReactDOM.render(<TableBox />, document.getElementById('root'));
&#13;
div#root {
  margin: 0 auto;
  width: 50%; }

img {
  width: 32px; }

span {
  padding: 20px 5px; }

table {
  font-family: 'Arial';
  margin: 25px auto;
  border-collapse: collapse;
  border: 1px solid #eee;
  border-bottom: 2px solid #ccc0b8;
  box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1), 0px 10px 20px rgba(0, 0, 0, 0.05), 0px 20px 20px rgba(0, 0, 0, 0.05), 0px 30px 20px rgba(0, 0, 0, 0.05); }
  table tr:hover {
    background: #f4f4f4; }
    table tr:hover td {
      color: #555; }
  table tr th, table tr td {
    color: #999;
    border: 1px solid #eee;
    padding: 12px 35px;
    border-collapse: collapse; }
  table tr th {
    background: #619d9f;
    color: #fff;
    text-transform: uppercase;
    font-size: 12px; }
    table tr th.last {
      border-right: none; }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

docs的这一部分是相关的:

  

setState()不会立即改变this.state,但会创建待处理状态转换。在调用此方法后访问this.state可能会返回现有值。

这正是您正在做的事情:您正在呼叫this.setState({sortAllTime: true});并立即访问this.state.sortAllTime中的loadCampersFromServer。但这会返回旧值。因此,即使最终更新状态,您加载的数据也是“旧”数据。只有下一次(第二次)点击才会加载您期望的数据。

相反,将sortAllTime的值传递给loadCampersFromServer,并将sortAllTime的状态值与data一起设置:

loadCampersFromServer(sortAllTime) {
  // perform Ajax request to get `data` for `sortAllTime`
  // ...
  this.setState({sortAllTime, data});
  // ...
}

"use strict";
class TableBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            sortAllTime: true
        };
    }

    loadCampersFromServer(sortAllTime) {
        let templateURL = 'https://fcctop100.herokuapp.com/api/fccusers/top/';
        let url = sortAllTime ? (templateURL + 'alltime') : (templateURL + 'recent');
        fetch(url)
            .then(
                (response) => {
                    if (response.status !== 200) {
                        console.log('Looks like there was a problem. Status Code: ${response.status}');
                        return;
                    }
                    response.json().then((data) => {
                        this.setState({data, sortAllTime});

                    })
                }
            )
            .catch(function (err) {
                console.log('Fetch Error :-S', err);
            });
    }

    _handlerAll() {
        this.loadCampersFromServer(true);
    }

    _handler30() {
        this.loadCampersFromServer(false);
    }

    componentDidMount() {
        this.loadCampersFromServer();
    }

    render() {
        return <CampersList _data={this.state.data}
        _handlerAll={this._handlerAll.bind(this)} _handler30={this._handler30.bind(this)}/>;
    }
}

class CampersList extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        let campersNodes = this.props._data.map((element, index) => {
            return (
                <Camper user={element} index={index}/>

            );
        });

        return (
            <table>
                <tr>
                    <th>#</th>
                    <th>Camper's Name</th>
                    <th onClick={this.props._handler30}>Points in past 30 days</th>
                    <th onClick={this.props._handlerAll}>All time points</th>
                </tr>
                {campersNodes}
            </table>
        )
    }
}

class Camper extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <tr>
                <td>{this.props.index + 1}</td>
                <td>
                    <img src={this.props.user.img} alt="logo"/>
                    <span>{this.props.user.username}</span>
                </td>
                <td>{this.props.user.recent}</td>
                <td>{this.props.user.alltime}</td>
            </tr>
        )
    }
}

ReactDOM.render(<TableBox />, document.getElementById('root'));
div#root {
  margin: 0 auto;
  width: 50%; }

img {
  width: 32px; }

span {
  padding: 20px 5px; }

table {
  font-family: 'Arial';
  margin: 25px auto;
  border-collapse: collapse;
  border: 1px solid #eee;
  border-bottom: 2px solid #ccc0b8;
  box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1), 0px 10px 20px rgba(0, 0, 0, 0.05), 0px 20px 20px rgba(0, 0, 0, 0.05), 0px 30px 20px rgba(0, 0, 0, 0.05); }
  table tr:hover {
    background: #f4f4f4; }
    table tr:hover td {
      color: #555; }
  table tr th, table tr td {
    color: #999;
    border: 1px solid #eee;
    padding: 12px 35px;
    border-collapse: collapse; }
  table tr th {
    background: #619d9f;
    color: #fff;
    text-transform: uppercase;
    font-size: 12px; }
    table tr th.last {
      border-right: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>