React Chatbox, как отобразить строку? - PullRequest
0 голосов
/ 21 февраля 2020

Я новичок ie и пытаюсь создать простое веб-приложение с рекомендациями ресторана, используя AWS и React. Итак, я использую это окно чата (https://www.npmjs.com/package/react-chat-window). По сути, когда пользователь что-то вводит, запускается чат-робот и задает вопросы типа «какую пищу вы хотите?» Пока что я могу передать ввод пользователя и получить ответ от AWS. Я могу записать ответ на консоль и проверить его. Но у меня проблемы с отображением ответа в окне чата.

Вот фрагмент кода

class chatBox extends Component {
    constructor() {
        super();
        this.state = {
            messageList: chatHistory,
            newMessagesCount: 0,
            isOpen: false
        };
    }

    // message is the user's input
    _onMessageWasSent(message) {
        var body = {
            messages: message.data['text']
        }
        // every time the user types something, this function passes the user's input to AWS
        apigClient.invokeApi(pathParams, pathTemplate, method, additionalParams, body)
            .then(function (result) { // result contains the response to the user's input
                var text = result.data.body
                console.log(text)   // logs the response to the user's input
                console.log(text.length)
            }).catch(function (result) {
            });

        this.setState({ //this displays what the user types
            messageList: [...this.state.messageList, message]
        })
    }


    // This is a function that displays the input of the other side
    // I can manually test it and see that whatever I pass to this function gets displayed as
    // the other person's speech, not the user.
    _sendMessage(text) {
        console.log("sendMessage")
        if (text.length > 0) {
            this.setState({
                messageList: [...this.state.messageList, {
                    author: 'them',
                    type: 'text',
                    data: { text }
                }],
                newMessagesCount: this.state.newMessagesCount + 1
            })
        }
    }

Как видно, я записываю ответ в консоль. Теперь я хочу отобразить ответ, поэтому я попробовал внутри конструктора

this._onMessageWasSent = this._sendMessage.bind(this)

и вызвав функцию внутри _onMessageSent

apigClient.invokeApi(pathParams, pathTemplate, method, additionalParams, body)
            .then(function (result) { // result contains the response to the user's input
                var text = result.data.body
                console.log(text)   // logs the response to the user's input
                console.log(text.length)
                this._sendMessage(text) // Calling the function
            }).catch(function (result) {
            });

        this.setState({ //this displays what the user types
            messageList: [...this.state.messageList, message]
        })
    }

Я вижу, что функция _sendMessage срабатывает, потому что У меня есть console.log. Но теперь окно чата не отображает ни пользователя, ни чата. Если я не связываю this._onMessageWasSent = this._sendMessage.bind (this), по крайней мере, я отображаю пользователя.

В чем может быть проблема ??

Это мой рендер ()

render() {
        return (<div>
            <Launcher
                agentProfile={{
                    teamName: 'Foodophile',
                    imageUrl: 'https://a.slack-edge.com/66f9/img/avatars-teams/ava_0001-34.png'
                }}
                onMessageWasSent={this._onMessageWasSent.bind(this)}
                messageList={this.state.messageList}
                onFilesSelected={this._onFilesSelected.bind(this)}
                newMessagesCount={this.state.newMessagesCount}
                handleClick={this._handleClick.bind(this)}
                isOpen={this.state.isOpen}
                showEmoji
            />
        </div>)
    }

enter image description here

ОБНОВЛЕНИЕ

class chatBox extends Component {
    constructor(props) {
        super(props);
        this.state = {
            messageList: chatHistory,
            newMessagesCount: 0,
            isOpen: false
        };
        this._onMessageWasSent = this._onMessageWasSent.bind(this);
        this._onFilesSelected = this._onFilesSelected.bind(this);
        this._handleClick = this._handleClick.bind(this);
        this._sendMessage = this._sendMessage.bind(this);
    }
    _onMessageWasSent(message) {
        var body = {
            messages: message.data['text']
        }

        apigClient.invokeApi(pathParams, pathTemplate, method, additionalParams, body)
            .then(function (result) {
                var text = result.data.body
                console.log(text)
                console.log(text.length)
                this._sendMessage(text)
            }).catch(function (result) {
            });
        this.setState({
            messageList: [...this.state.messageList, message]
        })
    }

    _sendMessage(text) {
        console.log("sendMessage")
        if (text.length > 0) {
            this.setState({
                messageList: [...this.state.messageList, {
                    author: 'them',
                    type: 'text',
                    data: { text }
                }],
                newMessagesCount: this.state.newMessagesCount + 1
            })
        }
    }
    render() {
        return (<div>
            <Launcher
                agentProfile={{
                    teamName: 'Foodophile',
                    imageUrl: 'https://a.slack-edge.com/66f9/img/avatars-teams/ava_0001-34.png'
                }}
                onMessageWasSent={this._onMessageWasSent}
                messageList={this.state.messageList}
                onFilesSelected={this._onFilesSelected}
                newMessagesCount={this.state.newMessagesCount}
                handleClick={this._handleClick}
                isOpen={this.state.isOpen}
                showEmoji
            />
        </div>)
    }

1 Ответ

1 голос
/ 21 февраля 2020

Вы должны связать свои методы класса в компонентах класса, чтобы вызвать их с помощью this. Но вы должны сделать это, например, в конструкторе, НО не в вашей функции рендеринга!

Посмотрите это очень хорошее объяснение о том, почему и как связывать ваши функции.

  constructor( props ){
    super( props );
    this._onMessageWasSent = this._onMessageWasSent.bind(this);
    this._onFilesSelected = this._onFilesSelected.bind(this);
    this._handleClick = this._handleClick.bind(this);
    this._sendMessage = this._sendMessage.bind(this);
  }

В вашей функции рендеринга просто передайте функции следующим образом:

render() {
        return (<div>
            <Launcher
                agentProfile={{
                    teamName: 'Foodophile',
                    imageUrl: 'https://a.slack-edge.com/66f9/img/avatars-teams/ava_0001-34.png'
                }}
                onMessageWasSent={this._onMessageWasSent}
                messageList={this.state.messageList}
                onFilesSelected={this._onFilesSelected}
                newMessagesCount={this.state.newMessagesCount}
                handleClick={this._handleClick}
                isOpen={this.state.isOpen}
                showEmoji
            />
        </div>)
    }

Также есть еще одна проблема. Привязка This - сложная вещь в JavaScript, а функции-стрелки function против ()=>{} обрабатывают это по-разному. В вашем случае просто используйте вместо этого функцию со стрелкой.

apigClient.invokeApi(pathParams, pathTemplate, method, additionalParams, body)
            .then((result) => {
                var text = result.data.body
                console.log(text)
                console.log(text.length)
                this._sendMessage(text)
            }).catch(function (result) {
            });

Это гарантирует, что this внутри вашей функции обратного вызова по-прежнему будет this, как вы ожидаете. Вот почему, если бы вы реорганизовали все свои функции (_onMessageWasSent, _onMessageWasSent, _onFilesSelected, handleClick, _sendMessage) в функции стрелок, больше нет необходимости связывать их с этим в конструкторе.

См. Например:

_onMessageWasSent = (message) =>  {
   // your function body
}

Вы уже можете избавиться от строки this._onMessageWasSent = this._onMessageWasSent.bind(this);.

Подробнее об этой привязке в функциях в w3school .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...