Извлечение текста данных из ответа API и представление его в чате с React - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть пользовательский интерфейс чата, в котором пользователь должен вводить текст и получать некоторые данные от службы ответа API.Пользовательский интерфейс работает нормально, и пользовательский текст представлен в чате, но ответ от API, полученный в формате JSON, вообще не представлен в чате (даже сообщение об ошибке от API, которое должно появиться в сообщении '').'поле, которое является тем же полем, в котором должен быть представлен результат). Насколько я знаю, я все настроил нормально, хотя я не знаю, что-то не так в методе рендеринга.

Примечание:предварительно сконфигурированные сообщения в состоянии чата в начале предназначены только для тестирования.

Операция Fetch в методе componentDidUpdate () в первом блоке кода, который я опубликовал.

 import React from "react";
import ReactDOM from "react-dom";
import "./App.css";

import Message from "./Message.js";

class Chatroom extends React.Component {
  constructor(props) {
    super(props);

    this.state = {

      chats: [
        {
          username: "clientUser",
          content: <p>Hello World!</p>,
          img:
            "http://***.jpg"
        },
        {
          username: "user2",
          content: <p>Hi,my name is user2.What's up ??</p>

        },
        {
          username: "user3",
          content: <p>Hi,my name is user3.What's up ??</p>
        },
        {
          username: "user4",
          content: <p>Hi,my name is user4.What's up ??</p>
        },
        {
          username: "userN",
          content: <p>Hi,my name is userN.What's up ??</p>,
          img: "http://***.jpg"
        },
        {
          username: "user5",
          content: <p>Hi,my name is user5.What's up ??</p>
        },
        {
          username: "user6",
          content: <p>Hi,my name is user6.What's up ??</p>
        },
        {
          username: "user7",
          content: <p>Hi,my name is user7.What's up ??</p>
        }
      ]
    };

    this.submitMessage = this.submitMessage.bind(this);
  }

  componentDidMount() {
    this.scrollToBot();

  }

  componentDidUpdate() {
    this.scrollToBot();


    fetch(
      "https://****",
      {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json"

        },
        body: JSON.stringify({
          inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
        })
      }
    ).then(response => response.json())
      .then(parsedJSON =>
        parsedJSON.results.map((
          user
        ) => ({

          username: "BotResponse",
          content: `${user.message}',
          img: "http://***.jpg"
        }))
      )
      .then(chats =>
        this.setState({
          chats
        })
      )
      .catch(error => console.log("parsing failed", error));


  }

  scrollToBot() {
    ReactDOM.findDOMNode(this.refs.chats).scrollTop = ReactDOM.findDOMNode(
      this.refs.chats
    ).scrollHeight;
  }

Метод отправки сообщения:

submitMessage(e) {

        e.preventDefault();




        this.setState(
          {
            chats: this.state.chats.concat([

              {
                username: "clientUser",

                content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,

                img: "http://***.jpg"
              }


            ])
          },
          () => {

            ReactDOM.findDOMNode(this.refs.msg).value = "";
          }

        );


      }  

Метод визуализации:

  render() {

    const username = "clientUser";
    const { chats } = this.state;

    return (
      <div className="chatroom">
        <h3>
          Title
        </h3>

        <ul className="chats" ref="chats">
          {chats.map((
            chat //Defines message component
          ) => (
            <Message chat={chat} user={username} />
          ))}
        </ul>
        <form className="input" onSubmit={e => this.submitMessage(e)}>
          <input type="text" ref="msg" />
          <input type="submit" value="Submit" />
        </form>
      </div>
    );
  }
}

export default Chatroom;

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Есть много вопросов для обсуждения вашего кода.Чтобы этот ответ был простым и целенаправленным, я просто расскажу о вашем fetch api call и о том, почему вы не видите ничего на переднем крае.

Во-первых, я предлагаю изучить методы жизненного цикла в документации React.Вы можете найти это здесь .Если эта ссылка не работает, просто перейдите на страницу документации React и выполните поиск «Методы LifeCycle».

Причина, по которой я привел это, заключается в том, что вы post вводите свои данные каждый раз, когда компонент обновляется, а не когда пользователь отправляет свое сообщение в чате.Итак, в тот момент, когда пользователь отправляет запрос, вы вызываете функцию onSubmit, которая вызывает setState.Установка состояния обновит пост.Так что в любом месте вашего кода, когда вы вносите изменения в свое состояние или если есть изменения в реквизитах вашего компонента, DOM будет обновляться, и будет запускаться componentDidUpdate, и вы будете публиковать снова.

Поместите свой вызов после API в функцию onSubmit.Обновите свою форму с этого:

 submitMessage(e) {
    e.preventDefault();
    this.setState(
      {
        chats: this.state.chats.concat([

          {
            username: "clientUser",

            content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,

            img: "http://***.jpg"
          }
        ])
      },
      () => {

        ReactDOM.findDOMNode(this.refs.msg).value = "";
      }
    );
  }

до этой обновленной функции onSubmit:

submitMessage(e) {
    e.preventDefault();
    fetch(
  "https://****",
  {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json"

    },
    body: JSON.stringify({
      inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
    })
  }
).then(response => response.json())
  .then(parsedJSON => {
    parsedJSON.results.map((
      user
    ) => ({

      username: "BotResponse",
      content: `${user.message}',
      img: "http://***.jpg"
    }))
   }
  )
  .then(chats =>
    this.setState({
      chats
    })
  )
  .catch(error => console.log("parsing failed", error));

   //for the sake of readability and debugging, you might want to store 
   that obj in a local variable here and put that variable in place of ...[]
    this.setState(
      {
        chats: [
          ...this.state.chats,
          {
            username: "clientUser",

            content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,

            img: "http://***.jpg"
          }
        ]
      },
      () => {
        ReactDOM.findDOMNode(this.refs.msg).value = "";
      }
    );
  }

Back-end

Вы хотите подтвердить, чтоэто на самом деле сохранение в вашу базу данных (может показаться очевидным, но дважды проверьте, что вы сохраняете так, как вы хотите и , что вы возвращаете правильную информацию. в правильном формате на спине-end. Это может быть, где проблема. Записать ваш ответ на вашу внутреннюю консоль и убедиться, что он возвращает все правильно.

Front-End

Посмотрите, как вы устанавливаете свое состояние в вызове извлечения. Я не совсем уверен, как вы отправляете свои данные, но вот пример вызова после извлечения с использованием axios.

axios.post("http://****", {
        data: this.state.data,
        more: this.state.more,
        etc: { example: "of", object: this.state.obj }
      })
      .then(response => {
        if (response.status === 200) {
          //do something with response.data
          //this.setState({ data: response.data})
        }
      });

Там действительно нетНичего больше я не могу предложить. Я не совсем уверен, что вы пытаетесь достичь с источником, который вы предоставили.

Примечание

Есть нескольковещи, которые вы делаете во всем коде, что я не уверен, что вы ннужно сделать.Но я не учел это в этом ответе, потому что я не совсем уверен, каков ваш проект и ваши желаемые результаты.Но это должно помочь с проблемой рендеринга.Если этого не произойдет, посмотрите, как вы устанавливаете свое состояние в fetch api call.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ

Я не думаю, что вам нужно иметь три .then в вашем вызове API.После того, как вы проанализировали свой JSON, вы можете установить свое состояние там.

РЕДАКТИРОВАТЬ 2

Приведенный выше источник не дал желаемого результата.Вызов API fetch не возвращал данные второму, а затем вызывающему, потому что данные из первого затем вызывают.Вот обновленная функция submitMessage.

submitMessage(e) {
        e.preventDefault();
        fetch(
      "https://****",
      {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json"

        },
        body: JSON.stringify({
          inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
        })
      }
    ).then(response => {
          return response.json() //here was the problem, nothing was being returned
       })
      .then(parsedJSON => {
        parsedJSON.results.map(user => ({
          username: "BotResponse",
          content: user.message, //this shouldn't need to be a string literal
          img: "http://***.jpg"
         })
        )
       }
      )
      .then(chats =>
        this.setState({
          chats
        })
      )
      .catch(error => console.log("parsing failed", error));
}
0 голосов
/ 11 декабря 2018

Проблема заключается в том, как вы думаете.Вы думаете, как если бы вы писали простой HTML с улучшениями JS.Реагирование - это фундаментальный сдвиг концепции.Вам нужно забыть многое из того, что вы знали из обычного, ванильного JS, чтобы выучить React.В React вы не заставляете HTMLElement выполнять операции, а работаете с локальным / глобальным состоянием и компонентами, чтобы объявить ваш пользовательский интерфейс.Полученный код является более производительным, обслуживаемым и без сбоев.

Чтобы вернуться к реальной проблеме, вам не следует использовать ref для получения значения вашего ввода.Вместо этого используйте onChange, чтобы установить состояние вашего сообщения и получить его позже, когда это необходимо.

Например:

export class MessageComposer extends React.Component {

  state = {
    fields: {
      message: ""
    }
  }

  clearField = fieldName => {
    this.setState({
      fields: {
        [fieldName]: ""
      }
    })
  }

  onInputChange = e => {
    this.setState({
      fields: {
        [e.target.name]: e.target.value
      }
    })
  }

  sendMessage = () => {
    const { fields: { message } } = this.state

    // Here you send the message contained into `message`.
    console.log(message)

    // Then you clean the message input value.
    this.clearField("message")
  }

  render () {
    const { fields: { message } } = this.state
    return (
      <div className="MessageComposer__container">
        <input 
          type="text"
          name="message"
          value={message}
          onChange={this.onInputChange}
        />
        <button onClick={this.sendMessage}>
          Submit
        </button>
      </div>
    )
  }

}

РЕДАКТИРОВАТЬ : только что увиделчто ваш код выборки включает в себя JSX.WTF?

Попробуйте изменить следующее:

body: JSON.stringify({
  inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
})

с версией без JSX.Не имеет смысла передавать компонент React, поскольку JSON.stringify даже не может сериализовать функцию (хорошо, вы получите, например, «Function» или «[Object object]» в inputText на вашем бэкэнде.я думаю).

Что-то вроде этого:

body: JSON.stringify({
  inputText: ReactDOM.findDOMNode(this.refs.msg).value
})

Кроме того, если по какой-либо причине React не находит ваш реф (т.е. компонент возвращает null или любую другую причину),inputText будет либо выдавать, либо возвращать undefined.

Если вы реорганизуете свой код, как я предлагал выше, вы можете сделать это:

body: JSON.stringify({
  inputText: this.state.fields.message
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...