awfha
awfha

Reputation: 128

How to prevent multiple entries between re-renders with Jotai?

I am using Jotai in a React app and have a problem where multiple entries are added between re-renders, causing duplicate data in the chatAtom. I tried using useState and local storage, which worked fine, but I want to stick with Jotai.

I'm not sure if the issue is related to state management or React's mounting/unmounting behavior. How can I prevent these multiple entries when using Jotai?

chatAtom:

import { atom } from 'jotai';

interface Chat {
  role: string | null;
  message: string | null;
  imageBase64?: string;
}

const chatAtom = atom<Chat[]>([]);

export default chatAtom;

Home.tsx

import { useEffect } from 'react';
import { useAtom } from 'jotai';
import chatAtom from '../store/chat.store';
import { Button } from '../components/ui/button';
import { useMutation } from '@tanstack/react-query';
import openAiService from '../services/openai.service';

function Home() {
  const [chat, setChat] = useAtom(chatAtom);

  const mutation = useMutation({
    mutationFn: openAiService.analyzeImage,
    onSuccess: (data) => {
      setChat((prev) => [
        ...prev,
        { role: 'bot', message: data },
      ]);
    },
    onError: (error) => {
      console.error('Error analyzing image:', error);
    },
  });

  useEffect(() => {
    const handleScreenRequest = (event: string) => {
      setChat((prev) => [
        ...prev,
        { role: 'user', message: 'What is this?', imageBase64: event },
      ]);
    };

    window.electron.ipcRenderer.on('screenshot-taken', handleScreenRequest);

    return () => {
      window.electron.ipcRenderer.removeListener('screenshot-taken', handleScreenRequest);
    };
  }, [setChat]);

  return (
    <div>
      <Button type="button" onClick={() => setChat([])}>Clean chat</Button>
      {chat.length < 1 && <p>No chat yet</p>}
      {chat.map((c, index) => (
        <div key={index}>
          <p>{c.role}</p>
          <p className="font-bold text-2xl mb-2">{c.message}</p>
          {c.imageBase64 && <img src={c.imageBase64} alt="screenshot" className="w-80 rounded-lg" />}
        </div>
      ))}
      {mutation.isPending && <p className="font-bold text-yellow-500">Loading...</p>}
    </div>
  );
}

export default Home;

Upvotes: 0

Views: 62

Answers (0)

Related Questions