Home > Blockchain >  React API call is not working as intended with setState()
React API call is not working as intended with setState()

Time:12-06

So here I'm fetching records by page. At mounting, I fetched page 1 and on next and prev button I'm changing the count, which is changing the page number and making a get request. But my code is not working correctly. It is giving me the result of count's previous state.

App.js

class App extends React.Component {


constructor(props) {
    super(props);
    this.state = {
      data: {},
      count: 1,
    };
  }



 handleApi = () => {
    fetch(`http://localhost:9000/accounts?page=${this.state.count}`)
      .then((res) => res.json())
      .then((res) => {
        this.setState({ data: res });
      })
      .catch((err) => console.log(err));
  };

  handlePrev = () => {
    if (this.state.count > 1) {
             this.setState((prevState) => ({
         count: prevState.count - 1
      }))
      this.handleApi();
    }
  };



handleNext = () => {
    if (this.state.count < this.state.data.total) {
      this.setState((prevState) => ({
         count: prevState.count   1
      }))
      this.handleApi();
    }
  };

  componentDidMount() {
    this.handleApi();
  }

  render() {
    return (
      <div className="App container">
        <h1 className="mb-3 text-center">Pagination Homepage</h1>

        {Object.keys(this.state.data).length !== 0 ? (
          <ListData detail={this.state.data} />
        ) : (
          <h4 className="mb-5 text-center">No Data to Show.</h4>
        )}

        <nav aria-label="Page navigation example">
          <ul className="pagination justify-content-center mt-4">
            <li className="page-item">
              <button
                className="btn btn-outline-primary me-3"
                onClick={this.handlePrev}
              >
                Prev
              </button>
            </li>

            <li className="page-item">
              <button
                className="btn btn-outline-success"
                onClick={this.handleNext}
              >
                Next
              </button>
            </li>
          </ul>
        </nav>
      </div>
    );
  }
}

export default App;

ListData.js

export default class ListData extends Component {
  render() {
    return (
      <div className="list-outer">

        <h4 className="mb-3 text-center"> List Data</h4>
        <div className="list-head">
          <p>Name</p>
          <p>E-mail</p>
        </div>
        {this.props.detail.data &&
          this.props.detail.data.map((list, index) => (
            <div key={list._id} className="list">
             
              <p className="list-item">{list.name.toUpperCase()} </p>
              <p className="list-item"> {list.mail}</p>
            </div>
          ))}
      </div>
    );
  }
}

Console

After updating the count the API is still calling count's previous state. Here page number in Data should be equal to the count. enter image description here

CodePudding user response:

Since setState works in an asynchronous way, after calling setState the this.state variable is not immediately changed. So if you want to perform an action immediately after setting state on a state variable and then return a result, use a callback:

  handlePrev = () => {
    if (this.state.count > 1) {
             this.setState((prevState) => ({
         count: prevState.count - 1
      }), () => this.handleApi());
    }
  };



handleNext = () => {
    if (this.state.count < this.state.data.total) {
      this.setState((prevState) => ({
         count: prevState.count   1
      }), () => this.handleApi());
    }
  };
  • Related