[英]Best way to fetch value from database to show on React front end
当用户单击按钮时,我试图在我的反应应用程序的客户端显示使用 mongoose 存储的集合属性的值。
通过在单击时检索值并使用 setState 存储该值。
我的问题——我似乎无法设置状态并立即显示新值 onClick... 在下一次单击时,显示的值是上一次单击的值。
我的后端 node.js 代码用于从 mongodb 获取数据
app.post('/api/showengagement', async (req, res) => {
const result = await Post.findOne({url: req.body.url}, "likes");
res.send(result);
})
我的前端 react.js 代码用于处理 onClick 并显示获取的数据
handleLike(url, e){
if (e.target.innerText.toLowerCase() === "like"){
axios.post('/api/showengagement', {url: url})
.then(res => this.setState({
likeEngage: res.data.likes
}));
e.target.innerText = `This post has ${this.state.likeEngage} like(s)`
axios.post('/api/incrementlikes', {url: url});
}
else{
e.target.innerText = "Like";
axios.post('/api/decrementlikes', {url: url});
}
}
谢谢您的帮助!
您看到错误的值是因为您在axios.post
完成之前设置了e.target.innerText
。 您可以将该代码移动到回调中以获得所需的操作顺序,如下所示:
handleLike = (url, e) => {
if (e.target.innerText.toLowerCase() === "like"){
axios.post('/api/showengagement', {url: url})
.then(res => {
e.target.innerText = `This post has ${res.data.likes} like(s)`
});
axios.post('/api/incrementlikes', {url: url});
}
else{
e.target.innerText = "Like";
axios.post('/api/decrementlikes', {url: url});
}
}
通过这种方式,您甚至不需要将值存储在state
中。 如果代码中的其他地方需要它,您仍然可以这样做。
您的innerText
设置发生在值返回之前的原因是axios.post
是异步的,并且在操作完成之前返回并且您的 function 继续到下一行(将文本设置为旧值)。 新值稍后在post
完成并调用您的回调 function 时出现。
另一种方法是让您的render()
function 负责使用state
变量将值写入适当的位置。 当您调用this.setState()
时,它会导致组件再次呈现,您会看到该值出现。 这是一个显示它的工作 React class:
import React from "react";
let likes = [];
let urls = ["url1", "url2"];
class Sample extends React.Component {
constructor(props) {
super(props);
this.state = { likeEngages: [] }; // initialize the array of likeEngages
}
// fake implementation of 'post' instead of axios.post
post = (url, body) => {
if (!likes[body.id]) likes[body.id] = 1;
if (url === "/api/showengagement") {
return Promise.resolve({ data: { likes: likes[body.id] } });
} else {
likes[body.id]++; // increment Likes for given id
return Promise.resolve();
}
};
handleLike = (url, e) => {
const id = e.target.id;
this.post("/api/showengagement", { url, id }).then(res => {
const engages = this.state.likeEngages;
engages[id] = res.data.likes; // set the likes count in the state
this.setState({ likeEngages: engages });
});
this.post("/api/incrementlikes", { url, id });
};
showLikes = id => {
if (this.state.likeEngages[id])
return (
<span>
{" This post has " + this.state.likeEngages[id] + " like(s)"}
</span>
);
return " No likes yet";
};
render() {
return (
<div>
<ul>
<li>
<button id="id1" onClick={e => this.handleLike(urls[0], e)}>
Like1
</button>
{this.showLikes("id1")}
</li>
<li>
<button id="id2" onClick={e => this.handleLike(urls[1], e)}>
Like2
</button>
{this.showLikes("id2")}
</li>
</ul>
</div>
);
}
}
export default Sample;
将您的 setState 更新为以下内容;
this.setState({...this.state, likeEngage: res.data.likes})
如果这不能解决问题,则需要在 setState 之后调用 incrementLikes,如下所示
this.setState({...this.state, likeEngage: res.data.likes}, () => incrementlikes(url))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.