React 中的分页与 REST API

waw*_*waw 2 reactjs react-router

最近在学习React,想知道如何在React中进行分页。我已经实现了一个简单的 REST API,它可以从数据库中获取数据并返回这样的 JSON 文件:

count: total number of data
start: starting index of data
limit: how many data per page
next: api to fetch next page of data
previous: api to fetch previous page of data

{
    "count": 17,
    "start": 1
    "limit": 5,
    "next": "/User/page?start=6&limit=5",
    "previous": "",
    "results": [
        {
            "email": "",
            "first_name": "",
            "id": ,
            "last_name": "",
            "password": "",
        },
        ...
    ], 
}
Run Code Online (Sandbox Code Playgroud)

我想所以我想在每个页面的底部添加两个链接,以便我可以前进和后退。

我当前的 React 代码如下所示,我可以从第一页获取数据,但我不确定如何进入下一页

class Users extends Component{
    state={
        count:undefined,
        limit:undefined,
        next:'',
        previous:'',
        start:undefined,
        results:[]
    }
    componentDidMount(){
        Axios.get('http://127.0.0.1:5000/User/page').then(response=>{
            this.setState({
                results:response.data.results,
                count:response.data.count,
                limit:response.data.limit,
                next:response.data.next,
                previous:response.data.previous,
                start:response.data.start
            })

        })
    }

    render(){
        console.log(this.state.previous)
        console.log(this.state.next)
        return (
            <div>
                {this.state.results.map((user)=>{return <User key={user.id} user={user}/>})}

                //I know this wont work
                //<a href={this.state.previous} style={{color:'#4c4c4c'}}>prev</a>
                //<br/>
                //<a href={this.state.next} style={{color:'#4c4c4c'}}>next</a>
            </div>

        )
    }
}
Run Code Online (Sandbox Code Playgroud)

Lin*_*ste 5

您希望页面上显示的内容反映地址栏中的 URL,反之亦然。因此,与其使用本地组件状态来控制页码,我们将使用 URL 中的页码作为“唯一的真实来源”。

路由器

在声明路由时,react-router-dom您可以使用冒号:后跟变量名来匹配动态变量。该变量将通过props.match.paramsuseParams钩子对组件可用。

在我们的例子中,我们想要一个变量pageNumber。主要路线如下所示:

<Route path="/users/page/:pageNumber" component={Users} />
Run Code Online (Sandbox Code Playgroud)

您问是否应该将流量从 重定向/users/users/page/1,在我看来,我们应该做相反的事情。我们可以使用我们Redirect内部的组件Switch来处理重定向。

当路由流量的/users页面,这一点很重要,这个页面去的一个附页码,否则它会匹配所有的页面。您也可以使用 param exact,但只要顺序正确就不需要。react-router 的一个普遍原则是,更具体的路径总是最先出现的。

同样,我们希望把我们Redirect 之前Route这会发送这些用户的Users页面。我们仍然会将它们发送到那里,但我们想先重定向。

<BrowserRouter>
  <Switch>
    <Redirect from="/users/page/1" to="/users" />
    <Route path="/users/page/:pageNumber" component={Users} />
    <Route path="/users" component={Users} />
    <Route path="/" component={Home} />
  </Switch>
</BrowserRouter>
Run Code Online (Sandbox Code Playgroud)

组件

我们的Users组件可以通过查看pageNumberfromprops.match.params.pageNumberuseParamshook来确定要呈现哪个页面。URL 参数总是 a string,所以我们需要parseInt在任何数学运算中使用它之前使用它。

当我们在第一页时,没有pageNumber参数,所以我们需要1在页码为空时默认为。

const params = useParams();
const pageNumber = params.pageNumber ? parseInt(params.pageNumber, 10) : 1;
Run Code Online (Sandbox Code Playgroud)

您将 API 调用基于pageNumber. 您可以使用字符串文字语法来组成正确的 URL 字符串。

axios.get(`http://127.0.0.1:5000/User/page?start=${1 + limit * (pageNumber - 1)}&limit=${limit}`);
Run Code Online (Sandbox Code Playgroud)

PreviousNext链接应该有条件地表示,因为是从第1页没有以前的页面,您可以使用API调用的结果,看是否有下一个页面。

const hasPrevious = pageNumber > 1;
const hasNext = !!state.next;
Run Code Online (Sandbox Code Playgroud)

我们使用Link来自的组件实现这些链接react-router-dom。该toPARAM需要,我们要链接到路径。我们将从当前的pageNumber.

<div>
   {hasPrevious && (
        <Link to={`/users/page/${pageNumber - 1}`}>Previous</Link>
    )}
    {hasNext && (
       <Link to={`/users/page/${pageNumber + 1}`}>Next</Link>
    )}
</div>
Run Code Online (Sandbox Code Playgroud)

显然我无权访问您的 API,但我创建了一个小演示以确保我的分页正确。

有关所用特定组件的更多信息,请务必查看React Router Docs