LoginSignup
2
2

More than 3 years have passed since last update.

Semantic-ui-reactを用いて一意のURLに対応したページネーションを実装した【React】

Last updated at Posted at 2019-09-11

概要

semantic-ui-reactを用いてページネーションの機能を実装していたのですが、
ページネーションの番号とURLが一意に対応するように実装をしてみました。

これによって、例えば戻るボタンで別ページからページネーションのページに戻った際に
常にデフォルトで設定されてるページ番号に遷移してしまう現象を防げます。

実装

まずはページネーションで扱う変数を定義します。

List.tsx
interface ArticleState {
  articleFromApi: Article[];
  articleToDisplay: Article[];
  begin: number;
  end: number;
  activePage: number;
  redirect: boolean;
}
  • articleFromApi -> apiから取得した全データ
  • articleToDisplay -> articleFromApiからページネーションで表示するデータだけ抽出したもの
  • begin -> articleFromApiからarticleToDisplayに抽出する初めのデータの数字を記録
  • end -> articleFromApiからarticleToDisplayに抽出する最後のデータの数字を記録
  • activePage -> クリックされたorされているページネーション番号を記憶しておく変数

コンストラクタを設定します

List.tsx
  constructor(props: RouteComponentProps<{id: string}>) {
    super(props);
    this.state = {
      articleFromApi: [],
      articleToDisplay: [],
      begin: 0,
      end: 5,
      activePage: 1,
      redirect: false,
    };
    this.getArticle = this.getArticle.bind(this);
    this.pageChange = this.pageChange.bind(this);
    this.setList = this.setList.bind(this);
    this.setActiveList = this.setActiveList.bind(this);
  }
  • デフォルトではページネーション先頭の「1」番目を開くようにactivePage: 1と設定しています。
  • 1ページにつき5つのデータが表示されるようにしているので、初期のstartendはそれぞれ0,5です。
List.tsx
  async pageChange(
    event: React.MouseEvent<HTMLAnchorElement>,
    data: PaginationProps
  ) {
    await this.setState({activePage: data.activePage as number});
    await this.setActiveList();
    this.setState({redirect: true});
  }

  async setActiveList() {
    await this.setState({begin: this.state.activePage * 5 - 5});
    await this.setState({end: this.state.activePage * 5});
    this.setState(
      {
        articleToDisplay: this.state.articleFromApi.slice(
          this.state.begin,
          this.state.end
        ),
      },
      () => window.scrollTo(0, 0)
    );
  }

  async componentDidMount() {
    this.setState({articleFromApi: []});
    await this.getArticle();
    await this.setState({activePage: Number(this.props.match.params.id)});
    this.setActiveList();
  }
  • 直接URLを叩いた際はcomponentDidMount() <- setActiveList()の順で参照されて、articleToDisplayが形成されます。
  • ページネーションコンポーネントがクリックされた際はpageChange() <- setActiveList()の順で参照されて、articleToDisplayが形成されます。
  • いずれの場合もやっていることは、ページネーション番号から表示するデータを抽出する作業です。

最後にコンポーネントをrenderします。

List.tsx
  render() {
    return (
      <Container style={{marginTop: '3em'}} text>
        <Grid columns={1} divided="vertically">
          <Grid.Row>
            {(this.state.articleToDisplay || []).map(function(articleData, i) {
              return (
                <Grid.Column>
                  <Segment>
                    <Header as="h1">{articleData.title}</Header>
                    <p style={{textOverflow: 'clip', wordBreak: 'break-all'}}>
                      {articleData.content.length > 100
                        ? articleData.content.substring(0, 97) + '...'
                        : articleData.content}
                    </p>
                    <Link to={`/detail/${articleData.id}`}>
                      continue reading
                    </Link>
                  </Segment>
                </Grid.Column>
              );
            })}
          </Grid.Row>
        </Grid>
        <Pagination
          defaultActivePage={this.props.match.params.id}
          totalPages={Math.ceil(this.state.articleFromApi.length / 5)}
          onPageChange={this.pageChange}
        />
        {this.renderRedirect()}
      </Container>
    );
  }
  • Grid内でarticleToDisplayを描写しています。
  • Pagination内でページネーションの諸々を設定しています。defaultActivePageはURLのパラーメーターと一致するように設定しています。totalPagesは1ページあたり5つのデータに対応するように設定しています。

また、URLのパラメーターとページネーション番号が一致するようにApp.tsxを設定します。

App.tsx
<Route exact path="/:id" component={List} />
List.tsx
export default withRouter(List);

ソースコード(全体)

以下のレポジトリに全貌のソースコードがあります。
https://github.com/jpskgc/article/blob/master/client/src/components/List.tsx

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2