繁体   English   中英

从数据库中获取值以显示在 React 前端的最佳方式

[英]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 时出现。

更好:避免使用 innerText - 使用 render()

另一种方法是让您的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM