Лучший способ получить значение из базы данных, чтобы показать на переднем конце React - PullRequest
0 голосов
/ 10 ноября 2019

Я пытаюсь отобразить значение свойства коллекции, хранящегося с помощью mongoose, на стороне клиента моего приложения реагирования, когда пользователь нажимает кнопку.

Получая значение при щелчке и сохраняя его, используяsetState.

Моя проблема - Кажется, я не могу установить 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);

})

Мой код реагирования внешнего интерфейса .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});
    }
}

Спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Вы видите неправильное значение, потому что вы устанавливаете e.target.innerText до того, как axios.post будет выполнено. Вы можете переместить этот код в функцию обратного вызова, чтобы получить желаемый порядок операций, например, такой:

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 является асинхронным и возвращается до завершения операциии ваша функция переходит к следующей строке (установка текста на старое значение). Новое значение появляется позже, когда post завершается и вызывается ваша функция обратного вызова.

Еще лучше: избегайте использования innerText - используйте render ()

Другой способ сделать это - это иметьВаша функция render() отвечает за запись значения в соответствующем месте с использованием переменной state. Когда вы вызываете this.setState(), это вызывает повторную визуализацию компонента, и вы увидите, что значение появляется. Вот рабочий класс React, который показывает это:

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;
0 голосов
/ 10 ноября 2019

Обновите ваш setState до следующего:

this.setState({...this.state, likeEngage: res.data.likes})

Если это не решит проблему, вам нужно будет вызывать incrementLikes после setState, как показано ниже

this.setState({...this.state, likeEngage: res.data.likes}, () => incrementlikes(url))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...