我具有以下外部JSON API:
{
"products": [
{
"id": 1,
"name": "Product Number 1",
},
{
"id": 2,
"name": "Product Number 2",
},
{
"id": 3,
"name": "Product Number 3",
}
],
"nextPage": "someapiurl.com/products?page=2"
}
API上的nextPage链接具有与上面相同的结构,但是具有不同的产品和指向第3页的链接。然后,第4、5、6,...页具有相同的结构。
我正在将其获取到Express服务器,并使用代理在React上使用数据。
这是我拥有的快递服务器:
const express = require('express');
const fetch = require('node-fetch');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/api', (req, res) => {
let url = 'someapiurl/products?page=1';
fetch(url).then((response) => response.json()).then((contents) =>
res.send({
products: contents.products,
nextPage: contents.nextPage
})
);
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT || 8080);
然后是我的react组件:
import React, { useEffect, useState } from 'react';
import fetch from 'node-fetch';
const IndexPage = () => {
const [ products, setProducts ] = useState([]);
const [ nextPage, setNextPage ] = useState('');
useEffect(() => {
const url = '/api';
fetch(url).then((response) => response.json()).then((contents) => {
setProducts([ ...products, ...contents.products ]);
setNextPage(contents.nextPage);
});
}, []);
return (
<div>
{products.map((product) => <p>{product.name}</p>)}
<button>Load More</button>
</div>
);
};
export default IndexPage;
我期望的是,当我单击“加载更多”时,发送状态nextPage进行表达,然后更改变量url。我的意图是将API第二页上的产品添加到产品状态,然后呈现到页面上。
如果更好,我可以将其更改为axios以查询数据。
答案 0 :(得分:0)
请参见以下示例:
class Feed extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
visible: 2,
error: false
};
this.loadMore = this.loadMore.bind(this);
}
loadMore() {
this.setState((prev) => {
return {visible: prev.visible + 4};
});
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/posts").then(
res => res.json()
).then(res => {
this.setState({
items: res
});
}).catch(error => {
console.error(error);
this.setState({
error: true
});
});
}
render() {
return (
<section>
<div>
{this.state.items.slice(0, this.state.visible).map((item, index) => {
return (
<div key={item.id}>
<span>{index+1}</span>
<h2>{item.title}</h2>
<p>{item.body}</p>
</div>
);
})}
</div>
{this.state.visible < this.state.items.length &&
<button onClick={this.loadMore} type="button">Load more</button>
}
</section>
);
}
}
ReactDOM.render(<Feed />, document.getElementById('feed'));
答案 1 :(得分:0)
根据React文档,componentDidMount
生命周期方法是加载一些初始数据的好地方。
... 如果您需要从远程端点加载数据,这是实例化网络请求的好地方... 您可以立即在componentDidMount()中调用setState()。它会触发额外的渲染,但是会在浏览器更新屏幕之前发生...
因此这是您获取第一个产品页面的地方。例如。 someapiurl.com/products?page=1
您可能还需要将下一页(nextPage
)值设置为nextPage
状态属性。
也许是这样的:
componentDidMount() {
fetch('someapiurl.com/products?page=1')
.then(response => response.json())
.then(json => {
this.setState({
products: json.products
nextPage: json.nextPage
})
})
}
现在,您可以根据products
状态属性来渲染产品。
return (
<React.Fragment>
<ul>{ this.state.products.map( product => (<li key={product.id}>{product.name}</li>) ) } </ul>
<button onClick={this.onNextPageClick}>next</button>
</React.Fragment>
);
使用button
调用函数以加载下一页,然后将更改products
和nextPage
状态属性。也许只需添加一个函数来获取数据,然后将nextPage
URL传递给它即可。
loadNextPage = url => {
fetch(url)
.then(response => response.json())
.then(json => {
this.setState({
products: json.products
nextPage: json.nextPage
})
})
}
因此,每当单击按钮时,onNextPageClick
处理程序将调用loadNextPage
当前设置为任何值的this.state.nextPage
。
onNextPageClick = event => {
this.loadNextPage(this.state.nextPage)
}
您可能还想看看Introducing Hooks
React钩子使您无需使用类或生命周期方法即可完成上述所有操作。
挂钩是React 16.8中的新增功能。它们使您无需编写类即可使用状态和其他React功能。
这里是一个使用React挂钩的示例,您可以根据需要进行调整。它只是通过增加每次点击的值来加载username
。由于我没有任何页面,因此我认为这会模仿您的情况。我相信你会明白的。
function LoadStuff () {
const [userId, setUserId] = React.useState(1);
const [userName, setUserName] = React.useState("")
const fetchUser = url => {
fetch(url)
.then(response => response.json())
.then(json => {
setUserName(json.name)
})
}
React.useEffect(() => {
fetchUser('https://jsonplaceholder.typicode.com/users/'+userId)
}, [userId])
const loadNextUser = () => (userId < 10) ? setUserId(userId + 1) : setUserId(1)
return (
<React.Fragment>
<div>
<p>{userId}</p>
<p>{userName}</p>
</div>
<button onClick={loadNextUser}>Load next user</button>
</React.Fragment>
);
}
ReactDOM.render(
<LoadStuff />,
document.getElementById('container')
);
<script src="https://unpkg.com/react@16.8.6/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>