使用React和Redux从API获取特定于日期的结果

Jam*_*een 12 javascript reactjs react-native redux react-redux

我想在使用Redux的React应用程序中显示一些新闻.

问题是我想显示个别日期的新闻,我想分页新闻.

在我的API我打印

{
  pagination: {
    count: 1000,
    size: 10,
    page: 1,
    pages: 100
  },
  news: [
    ..
  ]
}
Run Code Online (Sandbox Code Playgroud)

我知道如何进行简单的分页,但如果我希望能够在我的应用程序中显示不同日期的新闻,我不知道API应该如何工作.

到目前为止(没有日期),我刚刚保留了一个状态newspagination在我的Redux reducer中,然后检查页码是否等于总页数以确定是否应该尝试加载更多新闻.

但现在我可能有很多不同的日期,我想在Redux商店保留所有新闻,我不知道如何构建它.

我可以按原样保留我的API,因为使用GET参数进行过滤?date=15-09-2017只会减少API结果中的新闻数量.

但是仍然可以将所有新闻保存news在我的reducer 中的变量数组中,或者我是否必须将其构造成类似的东西

news: {
  '15-09-2017': {
    news: [...],
    pagination: {}
  },
  ...
}
Run Code Online (Sandbox Code Playgroud)

为了跟踪每个日期的分页?

flo*_*sse 8

认为一个结构,你按照id和id存储你的新闻每个日期将是良好和灵活的结构:

{
    "byId": {
        "10": { /* News */ },
        "14": { /* News */ },
        /* ... */
    },
    "listsByDate": {
        "2017-08-24": {
            "total": 100,
            "pageSize": 10,
            "page": 2,
            "items": [
                10,
                14,
                /* ... */
            ]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以为此结构实现简单的选择器:

const getNewsById = (state, id) => state.byId[id];

const getListByDate = (state, date) => state.listByDate[date];

const getPageOfList = (state, data) => getListByDate(state, date).page

/* ... */

const getNewsByDate = (state, date) => {
    return getListByDate(state, data).items.map((id) => {
        return getNewsById(state, id);
    });
}
Run Code Online (Sandbox Code Playgroud)


quo*_*Bro 1

我建议将所有新闻存储在一个位置(news在您的减速器中),并使用选择器来计算派生数据。

为了实现这一点,您需要将当前日期(我想它是您应用程序中的某种过滤器)存储在 Redux 存储中,以便可以在您的选择器中使用。

所以你的减速器将如下所示:

{
  news: [], // you can keep all the news here
  date: '15-09-2017', // selected date
  page: 1, // current page
  pagination: {
    '15-09-2017': { ... }, // pagination info by date.
    // You will need this only if you use the classic pager (with page numbers in UI)
    // it's not needed in case of infinite scroll
  }
}
Run Code Online (Sandbox Code Playgroud)

和选择器:

import { createSelector } from 'reselect';

// select all news
const newsSelector = () => (state) => state.get('news');

// select date
const dateSelector = () => (state) => state.get('date');

// select page
const pageSelector = () => (state) => state.get('page');

// select news by date
const newsByDateSelector = () => createSelector(
  newsSelector(),
  dateSelector(),
  (news, date, page) => news.filter((newsItem) => newsItem.get('date') === date)
);

const pageSize = 10;
const newsByDatePagedSelector = () => createSelector(
  newsByDateSelector(),
  pageSelector(),
  (news, page) => news.slice(pageSize  * (page - 1), pageSize * page)
);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用newsByDatePagedSelector选择器来获取容器中所需的新闻:

import React from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';

export class NewsContainer extends React.PureComponent {
  componentDidMount() {
    // news by selected date are not loaded yet
    if (!this.props.news) {
      this.loadNews();
    }
  }

  componentWillReceiveProps(nextProps) {
    // user navigated to the next page
    if (this.props.news && !nextProps.news) {
      this.loadNews();
    }
  }

  loadNews() {
    // fetch next 10 news from server
  }

  render() {
    return (
      <div>
        this.props.news.map((newsItem) => ...)
      </div>
    );
  }
}

const mapStateToProps = createStructuredSelector({
  news: newsByDatePagedSelector(),
});

export default connect(mapStateToProps)(NewsContainer);
Run Code Online (Sandbox Code Playgroud)

当用户在某个日期到达最后一条新闻时,您可以像往常一样使用过滤器从 API 请求接下来的 10 条新闻?date=15-09-2017,并将它们放入您的商店。Redux 和 reselect 会将它们作为NewsContainerprop newsByDate

  • 但是如何保留页码呢?如果我在一个页面上不断单击“加载更多”,直到到达第 10 页,总共有 100 (10 * 10) 条新闻,那么如果我转到另一个日期,我将不得不将页码重置为 1 才能加载第一个当天有 10 条新闻。但现在如果我回到第一个日期,我不想加载前 100 条新闻,因为我已经加载了这些? (2认同)