【问题标题】:Best practice to handle data from API call and render React components处理来自 API 调用和渲染 React 组件的数据的最佳实践
【发布时间】:2019-10-15 14:29:41
【问题描述】:

我对 React 有点陌生,并在我的 React/Redux/Firebase PWA 中寻找针对特定情况的最佳实践。现在,我关心的部分本质上是 Yelp API 的包装器。

我有一个主要组件,它在加载时(在 componentDidMount 内部)根据应用程序其他地方收到的用户偏好来查询 Yelp API。该组件还使用用户输入查询表单提交上的 API。它遍历来自两者的数据,并将道具传递给子组件。此视图看起来像是从 API 接收到的所有业务的列表。下面是一个示例:

"businesses": [
    {
      "rating": 4,
      "price": "$",
      "phone": "+14152520800",
      "id": "E8RJkjfdcwgtyoPMjQ_Olg",
      "alias": "four-barrel-coffee-san-francisco",
      "is_closed": false,
      "categories": [
        {
          "alias": "coffee",
          "title": "Coffee & Tea"
        }
      ],
      "review_count": 1738,
      "name": "Four Barrel Coffee",
      "url": "https://www.yelp.com/biz/four-barrel-coffee-san-francisco",
      "coordinates": {
        "latitude": 37.7670169511878,
        "longitude": -122.42184275
      },
      "image_url": "http://s3-media2.fl.yelpcdn.com/bphoto/MmgtASP3l_t4tPCL1iAsCg/o.jpg",
      "location": {
        "city": "San Francisco",
        "country": "US",
        "address2": "",
        "address3": "",
        "state": "CA",
        "address1": "375 Valencia St",
        "zip_code": "94103"
      },
      "distance": 1604.23,
      "transactions": ["pickup", "delivery"]
    },
    // ...
  ],

如前所述,主组件将数据传递给子组件,子组件会呈现列表中的每个单个对象。该子组件还根据每个业务的 id 创建指向另一个组件的链接。现在,这个其他组件与单个子组件的外观完全相同,只是在不同的 URL 上。例如,主要组件是“/venues”,企业的单个页面是“/venue/E8RJkjfdcwgtyoPMjQ_Olg”。数据是从 Redux 状态(它是一个 HOC)中提取出来的,并过滤掉以找到该 id。

我遇到的问题是,当我在企业的单个页面上刷新页面时,Redux 状态被清除,因此无法正确呈现数据。为了尝试解决这个问题,我尝试让服务工作者缓存它需要的所有内容,但这不起作用。刷新最终只显示我创建的加载页面,因为它没有进行调用(这是预期的 - 不希望它这样做)并且它也没有从缓存中提取数据。

有没有更好的方法来完成在刷新后将数据一直获取到单个业务组件?还是缓存整个页面/API 响应的更好方法,以便在刷新时正确呈现?

我想我可以让它联系特定业务的 API,但我试图避免这种情况。

【问题讨论】:

    标签: reactjs axios


    【解决方案1】:

    我记得 Yelp API 有一个端点,您可以在其中获取单个企业的详细信息。也就是说,您应该为您的个人业务页面设置一个动态路由;例如/businesses/:id。然后,您可以在 route props 中访问此 query param,并从那里获取该特定业务的数据。

    类似这样的:

    class IndividualBusiness extends Component {
      // ...
    
      componentDidMount() {
        fetchBusinessById(this.props.match.id).then(setState(...))
        // ...
      }
    
      // ...
    }
    

    路线看起来像这样:

    <Route exact path="/businesses/:id" render={(routeProps) => <IndividualBusiness {...routeProps} />}/>
    

    但是当数据已经在 redux 存储中时呢?很简单,只需在您的componentDidMount() 中添加控制流即可。

    【讨论】:

    • 知道了,我了解到动态路由通常是处理这种情况的方法,但我想确保没有其他更好的方法。我试图避免对 API 进行额外调用,但我想这是唯一的方法
    • 我的意思是你可以将它们存储在 localStorage 中,它有一个非常基本的 API 可以使用。但我从未见过有人这样做。他们只是进行额外的 fetch 调用。
    • 明白了,这很公平。我实际上喜欢的是现在作为一个类进行调用,从 API 中获取更多有用的信息!
    • @Adam 不确定你所说的 类进行 fetch 调用是什么意思。你的意思是函数fetchBusinessById()?只是为了澄清 class 是组件。我错过了 extends Component 但只是添加了它
    【解决方案2】:

    你试过localStorage吗?有一个redux middleware for it。它看起来像这样:

    import {createStore, compose} from 'redux';
    import persist from 'redux-localstorage';
    
    const store = createStore(reducer, compose(...otherMiddleware, persist(['apiResponses'])))
    

    这应该使你的 redux 状态的 "apiResponses" 部分在浏览器重新加载时保持不变。

    【讨论】:

    • 有趣的选项,我会研究这个
    猜你喜欢
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 2020-06-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多