apollo+react实战项目 stepbystep(九)

分页

1、修改路由

我们修改一下路由,使用/top来显示投票前10的链接,使用/new/:page来根据页码每页显示固定条数的link.首页路由‘/’自动跳转到/new/1页面。

import React, { Component } from 'react';
import {Route,Switch,Redirect} from 'react-router-dom';
import Header from './Header';
import '../styles/App.css';
import LinkList from './LinkList';
import CreateLink from './CreateLink';
import Login from './Login';
import Search from './Search'

class App extends Component {
  render() {
    return (
      <div className="center w85">
        <Header />
        <div className="ph3 pv1 background-gray">
          <Switch>
            <Route exact path='/' render={()=><Redirect to='/new/1' />} />
            <Route  path='/top' component={LinkList} />
            <Route  path='/new/:page' component={LinkList} />
            <Route path='/create' component={CreateLink} />
            <Route path='/login' component={Login} />
            <Route path='/search' component={Search} />
          </Switch>
        </div>
      </div>
    );
  }
}

export default App;

  

2、修改Header.js增加相应的top链接

<Link to="/top" className="ml1 no-underline black">
  top
</Link>
<div className="ml1">|</div>

  

3、修改FEED_QUEYR查询,增加相应的参数

export const FEED_QUERY = gql`
  query FeedQuery($first: Int, $skip: Int, $orderBy: LinkOrderByInput) {
    feed(first: $first, skip: $skip, orderBy: $orderBy) {
      links {
        id
        createdAt
        url
        description
        postedBy {
          id
          name
        }
        votes {
          id
          user {
            id
          }
        }
      }
      count
    }
  }

  

4、根据当前页面地址信息获取参数

_getQueryVariables = () => {
  const isNewPage = this.props.location.pathname.includes('new')
  const page = parseInt(this.props.match.params.page, 10)

  const skip = isNewPage ? (page - 1) * LINKS_PER_PAGE : 0
  const first = isNewPage ? LINKS_PER_PAGE : 10
  const orderBy = isNewPage ? 'createdAt_DESC' : null
  return { first, skip, orderBy }
}

  

5、更新Query中的variables

<Query query={FEED_QUERY} variables={this._getQueryVariables()}>

  

6、引入常量每页显示的link条数,在constants.js文件中定义

export const LINKS_PER_PAGE = 5

 

7、在页面底部增加两个导航功能,一个是上一页,一个是下一页

render() {
  return (
    <Query query={FEED_QUERY} variables={this._getQueryVariables()}>
      {({ loading, error, data, subscribeToMore }) => {
        if (loading) return <div>Fetching</div>
        if (error) return <div>Error</div>

        this._subscribeToNewLinks(subscribeToMore)
        this._subscribeToNewVotes(subscribeToMore)

        const linksToRender = this._getLinksToRender(data)
        const isNewPage = this.props.location.pathname.includes('new')
        const pageIndex = this.props.match.params.page
          ? (this.props.match.params.page - 1) * LINKS_PER_PAGE
          : 0

        return (
          <Fragment>
            {linksToRender.map((link, index) => (
              <Link
                key={link.id}
                link={link}
                index={index + pageIndex}
                updateStoreAfterVote={this._updateCacheAfterVote}
              />
            ))}
            {isNewPage && (
              <div className="flex ml4 mv3 gray">
                <div className="pointer mr2" onClick={this._previousPage}>
                  Previous
                </div>
                <div className="pointer" onClick={() => this._nextPage(data)}>
                  Next
                </div>
              </div>
            )}
          </Fragment>
        )
      }}
    </Query>
  )
}

  linksToRender用来计算当前页需要渲染的links

  isNewPage用来确定是否显示上一个(Previous)和下一页(Next)的页面元素

  由于分页会导致每页的links的index出现重复,因此将每页的index+(当前页-1)*每页条数来使得index变得唯一。

下面我们要实现的是_getLinksToRender,_previousPage和_nextPage方法。

_getLinksToRender = data => {
  const isNewPage = this.props.location.pathname.includes('new')
  if (isNewPage) {
    return data.feed.links
  }
  const rankedLinks = data.feed.links.slice()
  rankedLinks.sort((l1, l2) => l2.votes.length - l1.votes.length)
  return rankedLinks
}

  如果是newpage,则返回查询结果,如果是top则返回跳票前10的结果。

_nextPage = data => {
  const page = parseInt(this.props.match.params.page, 10)
  if (page <= data.feed.count / LINKS_PER_PAGE) {
    const nextPage = page + 1
    this.props.history.push(`/new/${nextPage}`)
  }
}

_previousPage = () => {
  const page = parseInt(this.props.match.params.page, 10)
  if (page > 1) {
    const previousPage = page - 1
    this.props.history.push(`/new/${previousPage}`)
  }
}

  添加前一页和后一页,需要判断前一页和后一页是否有效。

8、最后更新update,由于update中使用了FEED_QUERY因此,需要在update中增加variables

更新投票

_updateCacheAfterVote = (store, createVote, linkId) => {
  const isNewPage = this.props.location.pathname.includes('new')
  const page = parseInt(this.props.match.params.page, 10)

  const skip = isNewPage ? (page - 1) * LINKS_PER_PAGE : 0
  const first = isNewPage ? LINKS_PER_PAGE : 100
  const orderBy = isNewPage ? 'createdAt_DESC' : null
  const data = store.readQuery({
    query: FEED_QUERY,
    variables: { first, skip, orderBy }
  })

  const votedLink = data.feed.links.find(link => link.id === linkId)
  votedLink.votes = createVote.link.votes
  store.writeQuery({ query: FEED_QUERY, data })
}

  

更新创建新链接

<Mutation
  mutation={POST_MUTATION}
  variables={{ description, url }}
  onCompleted={() => this.props.history.push('/new/1')}
  update={(store, { data: { post } }) => {
    const first = LINKS_PER_PAGE
    const skip = 0
    const orderBy = 'createdAt_DESC'
    const data = store.readQuery({
      query: FEED_QUERY,
      variables: { first, skip, orderBy }
    })
    data.feed.links.unshift(post)
    store.writeQuery({
      query: FEED_QUERY,
      data,
      variables: { first, skip, orderBy }
    })
  }}
>
  {postMutation => <button onClick={postMutation}>Submit</button>}
</Mutation>

  

 

posted @ 2018-09-07 13:07  tutu_python  阅读(200)  评论(0)    收藏  举报