简体   繁体   English

状态不会第一次改变

[英]The state does not change the first time

When I click on the "Next" button, state.page is updated the second time.当我点击“下一步”按钮时,state.page 第二次更新。 And if I scroll forward several times and want to bring out new repositories, it also outputs only from the second press.如果我向前滚动几次并想要显示新的存储库,它也只会从第二次按下时输出。 Help fix it.帮助修复它。 Project on CodeSandBox: https://codesandbox.io/s/lab9rest-api-eupg0 CodeSandBox 项目: https ://codesandbox.io/s/lab9rest-api-eupg0

Layout.js布局.js

import React from "react";
import axios from "axios";
import ReposList from "./ReposList";

export default class Layout extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      page: 1,
      pages: 100,
      per_page: 10
    };
  }

  searchNew() {
    this.setState(() => {
      return { page: 1 };
    });

    this.search();
  }

  search() {
    let text = document.getElementById("search-text").value;

    if (text !== "") {
      let sort = document.getElementById("sort-items").value;
      let sortValue = sort.split("-")[1];
      let pagination =
        "&page=" + this.state.page + "&per_page=" + this.state.per_page;
      let url =
        "https://api.github.com/search/repositories?q=" + text + pagination;

      if (sort === "best-matches") url += "&order=desc";

      if (sort === "most-stars") url += "&sort=" + sortValue + "&order=desc";

      if (sort === "fewest-stars") url += "&sort=" + sortValue + "&order=asc";

      if (sort === "most-followers")
        url += "&sort=" + sortValue + "&order=desc";

      if (sort === "fewest-followers")
        url += "&sort=" + sortValue + "&order=asc";

      if (sort === "most-forks") url += "&sort=" + sortValue + "&order=desc";

      if (sort === "fewest-forks") url += "&sort=" + sortValue + "&order=asc";
      console.log(this.state.page);
      axios(url)
        .then(response => {
          if (response.data.items.length !== 0) {
            this.setState(() => {
              return {
                data: response.data.items
              };
            });
          } else alert("Репозиториев не найдено.");
        })
        .catch(error => {
          alert("Не удалось обработать инструкции '" + text + "'.");
        });
    }
  }

  nextPage() {
    if (this.state.page !== this.state.pages)
      this.setState(state => {
        return { page: state.page + 1 };
      });
    else
      this.setState(() => {
        return { page: 1 };
      });

    this.search();
  }

  changePerPage() {
    let per_page = document.getElementById("per_page").value;
    let pages = Math.floor(1000 / per_page);
    console.log(pages);
    this.setState(() => {
      return { per_page: per_page, pages: pages };
    });
  }

  changeCurrentPage(page) {
    this.setState(() => {
      return { page: page };
    });
  }

  render() {
    return (
      <div>
        <h3>Repository search</h3>
        <div id="search">
          <select id="sort-items" onChange={() => this.changeCurrentPage(1)}>
            <option value="best-match">Best match</option>
            <option value="most-stars">Most stars</option>
            <option value="fewest-stars">Fewest stars</option>
            <option value="most-forks">Most forks</option>
            <option value="fewest-forks">Fewest forks</option>
            <option value="most-followers">Most followers</option>
            <option value="fewest-followers">Fewest followers</option>
          </select>
          <input type="text" id="search-text" />
          <button onClick={() => this.searchNew()}>Search</button>
        </div>
        <div id="settings">
          <p>output amount</p>
          <input
            type="number"
            min="1"
            defaultValue="10"
            max="100"
            id="per_page"
            onChange={() => this.changePerPage()}
          />
        </div>
        <ReposList data={this.state.data} />
        <div id="pagination">
          {this.state.page}
          <button onClick={() => this.nextPage()}>Next</button>
        </div>
      </div>
    );
  }
}

RepoList.js RepoList.js

import React from "react";
import Repo from "./Repo";

export default class ReposList extends React.Component {
  render() {
    return (
      <div id="repos">
        {this.props.data.map((repo, index) => {
          return (
            <Repo
              key={index}
              avatar={repo.owner.avatar_url}
              login={repo.owner.login}
              url={repo.url}
              name={repo.name}
            />
          );
        })}
      </div>
    );
  }
}

Repo.js回购协议

import React from "react";

export default function Repo(props) {
  return (
    <div className="repo">
      <img src={props.avatar} alt="avatar" />
      <p className="login">{props.login}</p>
      <a className="url" href={props.url}>
        {props.name}
      </a>
    </div>
  );
}

Actually, your state is being updated on the first click - but later.实际上,您的状态会在第一次点击时更新 - 但稍后。

setState is not a synchronous action that changes this.state right now , but it does it as soon as there is time to re-render . setState不是同步的行动,改变this.state的权利,但它尽快做它有时间重新呈现

So when you call this.search() directly after this.setState , this.state just hasn't been updated yet and you continue working with the old value.因此,当您在this.setState之后直接调用this.search()this.state尚未更新,您将继续使用旧值。

setState actuall accepts a callback as a second argument, so to make sure that this.search is only called after the state has persisted, you could do it like setState 实际上接受一个回调作为第二个参数,所以为了确保this.search只在状态持续this.search被调用,你可以这样做

searchNew() {
    this.setState(() => {
      return { page: 1 };
    },
    () => this.search()
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM