skip to Main Content

So I am creating a clone of Google Gemini using React js and I am keeping a useState hook to keep the track of the chat history in the format that gemini API requires (array of objects where each object has one property saying is it user or model and other property is object with just one property, the text). The problem is that when I give it one input the hook stores 1 input then response then again same input and again the same response whereas it should store only 1 input and 1 response.

The function’s code is :

const handleRun = async () => {
  setCall((prev) => prev + 1);
  console.log(call);
  if (input !== "") {
    console.log(conversationHistory);
    const response = await run(conversationHistory, input);
    setConversationHistory((prevHistory) => [
      ...prevHistory,
      { role: "user", parts: [{ text: input }] },
      { role: "model", parts: [{ text: response }] },
    ]);
    console.log(conversationHistory);
    setInput("");
  }
};

enter image description here

2

Answers


  1. It appears that your issue lies in the react hook’s asynchronous nature.

    When you call setConversationHistory, even though it may seem like it would immediately update conversationHistory, it doesn’t. The state update is enqueued by React and happens at some later time, which can lead to unexpected results when you’re trying to examine the state immediately after calling the update function (setConversationHistory in your case).

    You’re logging console.log(conversationHistory) right after updating the state, at a time when the state might not have been updated yet, which is why you’re not seeing the expected output.

    React guarantees the prevHistory value you’re using in your updater function is accurate, as it refers to the state at the time that specific update is being applied. Therefore, you might want to console log prevHistory instead:

    setConversationHistory(prevHistory => {
        const updatedHistory = [...prevHistory,
          { role: 'user', parts: [{ text: input }] }, 
          { role: 'model', parts: [{ text: response }] }];
        
        console.log(updatedHistory);
        return updatedHistory;
      });
    

    This helper variable updatedHistory will give you insight on the value being enqueued for state update.

    Alternatively, if you want to do something every time conversationHistory is being updated, consider using the useEffect hook:

    useEffect(() => {
      console.log(conversationHistory);
    }, [conversationHistory]); 
    

    This hook will be triggered every time conversationHistory changes, ensuring accurate reads every time.

    Login or Signup to reply.
  2. create a new array that combines the user message and the response with the existing history:

    setConversationHistory([
      ...conversationHistory,
      { role: 'user', parts: [{ text: input }] },
      { role: 'model', parts: [{ text: response }] },
    ]);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search