【问题标题】:Correct way to fetch data via API in React [closed]在 React 中通过 API 获取数据的正确方法 [关闭]
【发布时间】:2020-12-18 04:41:40
【问题描述】:

我正在学习 javascript 和 React,挑战(在 Hackerrank 实践中)是从具有多个页面的 API 获取数据。按钮的数量应该与页面数一样多,单击每个按钮时,该特定页面的数据应如下所示:

这是我写的组件:

import React from 'react';

const url = "https://jsonmock.hackerrank.com/api/articles?page=";
const default_page = 1;

class Articles extends React.Component {
  state = {
    pageCount: 1,
    body: {},
    currentPage: 1,
    error: null,
    isLoading: false,
    data: []
  };

  componentDidMount(){
    this.setState({isLoading: true});
    fetch(url+default_page)
    .then(response => response.json())
    .then(body => this.setState({
      pageCount: body.total_pages, 
      data: body.data,
      body: body,
    }))
    .catch(err => this.setState({error: err}));
  }

  pageButtonGenerator(){
    if(this.state.body){
      let pageButtons=[];
      for(var i=1; i<=this.state.pageCount; i++){
        const id = i; //need this to use in event handler, BUT WHY DOES i NOT WORK (the value is always i=this.state.pageCount)
        pageButtons.push(<button data-testid="page-button" key={"page-button-"+i} onClick={(e) => this.buttonClickHandler(id)}>{i}</button>);
      }
      return pageButtons;
    }
    else{
      return <button data-testid="page-button" key="page-button-1">1</button>
    }
  }

  buttonClickHandler = (pageNum) => {
    // console.log(pageNum);
    this.setState({isLoading: true});
    fetch(url+pageNum)
    .then(response => response.json())
    .then(body => this.setState({
      pageCount: body.total_pages, 
      data: body.data,
      body: body,
      currentPage: pageNum
    }))
    .catch(err => this.setState({error: err}));
    // this.titlesGenerator();
  }

  titlesGenerator = () => {
    if(this.state.data){
      return this.state.data.map((element,index) => {
        if(element.title){ return <li key={"title-"+index+1} data-testid="result-row">{element.title}</li> }
        else{ return null }
      })
      // console.log(this.state.data);
      
    }
  }

  render() {
    return (
      <React.Fragment>
        <div className="pagination">
          {this.pageButtonGenerator()}
        </div>
        <ul className="results">
        {this.titlesGenerator()}
        </ul>
      </React.Fragment>
    );
  }
}

export default Articles;

虽然我的代码通过了测试用例,但如果我做对了,我不是很有信心。我有这样的疑问:

  1. 我应该一次性获取所有页面以避免多次网络调用,还是应该在每次单击页面按钮时进行调用?
  2. 我生成按钮的方式是否正确(参见pageButtonGenerator)?
  3. pageButtonGenerator 的for 循环中,我是否以正确的方式调用onClick 处理程序?我试图直接传递变量“i”,但它总是 = 6(循环的退出值)。我很难理解为什么变量 i 也是 6。我认为关闭将确保该值始终正确..
  4. 我应该如何处理状态中存储的内容以及应该派生和不存储的内容?

接受建设性的批评。谢谢

【问题讨论】:

    标签: javascript reactjs design-patterns pagination fetch-api


    【解决方案1】:

    我试着用简单的术语来解释:

    我应该一次性获取所有页面以避免多次网络调用,还是应该在每次单击页面按钮时进行调用?

    答:如果您正在制作 Web 应用程序并且您有 500 个页面,则不认为这是实际场景。即使您不能说用户可以访问每个页面,在旅途中获取所有 500 个页面是否有意义。好的经验法则是您了解可用的总数据并执行pagination。例如用户点击 5 页。然后获取 5 页数据。在此之前,即使您不确定用户是否会点击,为什么您会在用户浏览器中添加开销。希望能回答这个问题。

    我生成按钮的方式是否正确(参见 pageButtonGenerator)?

    答:是的。学习分页的更好方法。但是您正在处理动态按钮生成权

    在 pageButtonGenerator 的 for 循环中,我是否以正确的方式调用 onClick 处理程序?我试图直接传递变量“i”,但它总是 = 6(循环的退出值)。我很难理解为什么变量 i 也是 6。我认为关闭将确保该值始终正确..

    A:是的,你是对的,它的关闭问题。它发生的原因是因为您正在使用

    for(var i=1; i<=this.state.pageCount; i++){
    //var keyword
    

    var 在 javascript 中是函数作用域,这意味着 var 位于函数作用域中,所以当buttonClickHandler 在循环已经运行后获取它的值时,即当循环关闭它的第 6 个时它已经设置了 5 次。这就是为什么它发送 6 作为 id。 最简单的解决方案是使用:letfor(let i=1; i&lt;=this.state.pageCount; i++){

    我应该如何处理状态中存储的内容以及应该派生和不存储的内容?

    一般来说,好的经验法则是errorloadingdata 状态。根据其组合,您可以显示结果。关键数据(如页数、当前数据)应存储在您的状态中,否则您将无法获得下一个和上一个状态

    【讨论】:

      【解决方案2】:
      1. 您为每个请求获取一个页面,原因很简单,如果所有用户访问的都是第 1 页,那么获取所有页面是多余的。

      2. &3:通常你宁愿创建一个小部件 React 组件,将分页器包装在一个单独的组件中,并将页面数传递给它。
        此小部件只是一个列表,您可以将其设置为分页小部件。
        所以确实,pageButtonGenerator 内部的逻辑有点不必要。
        4:在处理ajax时,通常我会具备三个属性:

        { isFetching,结果,错误}

      result 是一个嵌套对象,包含所有作为 ajax 调用结果的属性。
      属于分页的属性将被传递给分页小部件。
      可以派生的属性通常不存储;如果您忘记更新它们,则会导致错误。 Imo,最好在运行时派生。

      更多注释:

      • 这是 2020 年,如果可以,请使用功能组件。
      • 我不太喜欢在 React 组件中进行所有状态管理。
        如果您想要更清晰的关注点分离,请查看 Redux 和 Redux observable。
        这也将回答您的许多关于什么去哪里的问题。

      【讨论】:

        猜你喜欢
        • 2021-11-30
        • 1970-01-01
        • 1970-01-01
        • 2020-02-14
        • 2018-02-11
        • 2021-09-24
        • 2015-06-08
        • 2019-12-29
        • 2021-10-02
        相关资源
        最近更新 更多