I have a chatbot which generates answers, I need an auto-scroll function for it

85 views Asked by At

Auto-scroll to bottom in react: I have a chatbot that have conversations with people, I need it to scroll to the bottom automatically when it generates new answers.

I am not familiar with React and I am using a prepared code so I'm not sure how to implement the auto scroll. I tried some ways but it didn't work out.

here is my code:


function App() {
  const [messages, setMessages] = useState([
    {
      message: "Hello there! I'm your Health Assistant, designed to make your wait more comfortable and informative. Whether you have questions about your health, need general information, or just want a friendly chat, I'm here for you. Feel free to ask me anything, and let's make your time in the waiting room as pleasant as possible!",
      sentTime: "just now",
      sender: "ChatGPT"
    }
  ]);




  const [isTyping, setIsTyping] = useState(false);
  
  const handleSend = async (message) => {

  const newMessage = {
      message,
      direction: 'outgoing',
      sender: "user"
    };

  const newMessages = [...messages, newMessage];
    
    setMessages(newMessages);

    // Initial system message to determine ChatGPT functionality
    // How it responds, how it talks, etc.
    setIsTyping(true);
    await processMessageToChatGPT(newMessages);
  };

  async function processMessageToChatGPT(chatMessages) { // messages is an array of messages
    // Format messages for chatGPT API
    // API is expecting objects in format of { role: "user" or "assistant", "content": "message here"}
    // So we need to reformat

    let apiMessages = chatMessages.map((messageObject) => {
      let role = "";
      if (messageObject.sender === "ChatGPT") {
        role = "assistant";
      } else {
        role = "user";
      }
      return { role: role, content: messageObject.message}
    });


    // Get the request body set up with the model we plan to use
    // and the messages which we formatted above. We add a system message in the front to'
    // determine how we want chatGPT to act. 
    const apiRequestBody = {
      "model": "gpt-4",
      "messages": [
        systemMessage,  // The system message DEFINES the logic of our chatGPT
        ...apiMessages // The messages from our chat with ChatGPT
      ]
    }

    await fetch("https://api.openai.com/v1/chat/completions", 
    {
      method: "POST",
      headers: {
        "Authorization": "Bearer " + API_KEY,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(apiRequestBody)
    }).then((data) => {
      return data.json();
    }).then((data) => {
      console.log(data);
      setMessages([...chatMessages, {
        message: data.choices[0].message.content,
        sender: "ChatGPT"
      }]);
      setIsTyping(false);
    });
  }

  return (
    <div className="App">
      <div style={{ position:"relative", height: "550px", width: "900px"  }}>
        <MainContainer>

          <ChatContainer>       
            <MessageList 
              scrollBehavior="smooth" 
              typingIndicator={isTyping ? <TypingIndicator content="Chatbot is typing" /> : null}
            >
              {messages.map((message, i) => {
                console.log(message)
                return <Message key={i} model={message} />
              })}
            </MessageList>
            <MessageInput placeholder="Type message here" onSend={handleSend} attachButton={false} />        
          </ChatContainer>
        </MainContainer>

      </div>
    </div>
  )
}

export default App

1

There are 1 answers

1
Robert Clave On

Create a ref for the MessageList:

const messageListRef = useRef(null);

Add the ref to the MessageList element:

<MessageList
  ref={messageListRef}
  scrollBehavior="smooth"
  typingIndicator={isTyping ? <TypingIndicator content="Chatbot is typing" /> : null}
>
  {/* ... */}
</MessageList>

Scroll to the bottom after adding new messages:

useEffect(() => {
  messageListRef.current.scrollTo(0, messageListRef.current.scrollHeight);
}, [messages]);