javascript - 状态不会第一次改变

标签 javascript reactjs state

当我点击“下一步”按钮时,state.page 会第二次更新。如果我向前滚动几次并想要显示新的存储库,它也只会从第二次按下时输出。帮助修复它。 CodeSandBox 上的项目:https://codesandbox.io/s/lab9rest-api-eupg0

布局.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

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>
  );
}

最佳答案

实际上,您的状态会在第一次点击时更新 - 但稍后会更新。

setState 不是同步更改 this.state 的操作 立即,但它会立即执行是时候重新渲染了

所以当你在 this.setState 之后直接调用 this.search() 时,this.state 还没有更新,您继续使用旧值。

setState actuall accepts a callback作为第二个参数,为了确保 this.search 仅在状态持续存在后调用,您可以这样做

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

关于javascript - 状态不会第一次改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59276213/

相关文章:

javascript - 在 React Native 中使 View 为父级的 80% 宽度

reactjs - 如何集中不同的 proptypes

javascript - AngularJs ui-router $location 还是 $state?

C# 和 Oracle,登录表单 : Operation is not valid due to the current state of the object

javascript - 将 React HOC 与表单一起使用。使用 HOC 传递通用 JSX 和状态

javascript - 如何使用 Airbnb JavaScript 样式指南设置 Prettier

javascript - 如何将 IMEI 号码限制为仅 15 位数字且不计算 4 位数字后的空格

JavaScript 土耳其手机号码验证

javascript - 将所选语言保存在本地存储中?

reactjs - React 的 `window` 对象是合成的吗?