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>
浙公网安备 33010602011771号