⭐️ 채팅 기능 메세지와 이미지 업로드 구현
해당 코드는 Firebase를 사용하여 실시간 채팅 애플리케이션의 메시지 전송 기능을 구현하는데 사용되는
React 컴포넌트입니다.
import {
getDownloadURL,
ref,
uploadBytesResumable,
UploadTaskSnapshot,
} from '@firebase/storage';
import { db } from '@/firebase/app';
import { storage } from '@/firebase/storage';
import { BsFillSendFill } from 'react-icons/bs';
import classes from './SendMessage.module.scss';
import { AuthContext } from '@/context/AuthContext';
import { FormEvent, useContext, useState } from 'react';
import Img from '/public/assets/chatImagePlaceholder.svg';
import { collection, addDoc, serverTimestamp } from '@firebase/firestore';
export function SendMessage() {
const { currentUser } = useContext(AuthContext);
const [input, setInput] = useState('');
const [img, setImg] = useState(null);
const handleSendMessage = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (input === '') {
alert('메시지를 입력하세요');
return;
}
const { uid, displayName } = currentUser;
if (img) {
const uniqueId = img.name;
const storageRef = ref(storage, uniqueId);
const uploadTask = uploadBytesResumable(storageRef, img);
uploadTask.on(
'state_changed',
(snapshot: UploadTaskSnapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
},
(error) => {
console.log(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => {
await addDoc(collection(db, 'messages'), {
text: input,
name: displayName,
uid,
createdAt: serverTimestamp(),
photoURL: downloadURL,
});
});
}
);
} else {
await addDoc(collection(db, 'messages'), {
text: input,
name: displayName,
uid,
createdAt: serverTimestamp(),
});
}
setInput('');
setImg(null);
};
return (
<form className={classes.input} onSubmit={handleSendMessage}>
<div>
<img src={img} alt="" />
<label htmlFor="message" className="a11yHidden">
메세지 입력
</label>
<input
type="text"
placeholder="메시지를 입력하세요."
name="text"
id="message"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
</div>
<div className={classes.send}>
<input
type="file"
style={{ display: 'none' }}
id="file"
name="file"
accept="image/*"
onChange={(e) => setImg(e.target.files[0])}
/>
<label htmlFor="file">
<img src={Img} alt="이미지 업로드" />
</label>
<button type="submit">
<BsFillSendFill />
</button>
</div>
</form>
);
}
컴포넌트의 함수 SendMessage 내에는 currentUser 객체와 input 및 img 상태 변수가 있습니다.
이 currentUser 객체는 Firebase Authentication에서 현재 로그인된 사용자의 정보를 제공하는 컨텍스트로부터 가져옵니다.
handleSendMessage 함수는 메시지를 전송하는 데 사용됩니다.
이 함수는 폼 제출 이벤트를 처리하고, input 상태 변수가 비어 있으면 메시지를 입력하라는 경고 메시지를 표시하고 함수를 종료합니다.
그렇지 않으면 uid, displayName 및 input 값을 사용하여 messages 컬렉션에 새로운 메시지 문서를 추가합니다.
이미지가 포함된 경우 uniqueId라는 고유한 식별자를 생성하고 Firebase Storage의 ref 함수를 사용하여 storageRef 참조를 만듭니다. 이후 uploadBytesResumable 함수를 사용하여 파일의 업로드를 시작하고, on 메서드를 사용하여 업로드의 진행 상황을 확인합니다. 업로드가 완료되면 getDownloadURL 함수를 사용하여 업로드된 이미지의 URL을 가져옵니다. 이 URL은 messages 컬렉션에 새로운 메시지 문서를 추가할 때 함께 저장됩니다.
input 및 img 변수의 값을 초기화하고, 사용자가 이미지를 선택하면 setImg 함수가 호출되어 img 변수의 값을 업데이트합니다.
사용자가 이미지를 선택할 때는 "file" ID를 가진 파일 입력 필드의 onChange 이벤트가 트리거됩니다.
마지막으로, SendMessage 컴포넌트는 폼 요소를 렌더링하고, handleSendMessage 함수가 폼 제출 이벤트를 처리하도록 합니다. 이 요소에는 메시지 입력 필드, 이미지 선택 필드, 이미지 업로드 버튼 및 메시지 전송 버튼이 포함됩니다.
🧐 채팅기능 구현
➡️ 마우스를 사용하지 않고 탭키로만 이동하는 모습입니다.
'Project' 카테고리의 다른 글
로그인한 사용자별 다른 프로필 보이게 하기 (0) | 2023.04.06 |
---|---|
React에서 페이지 변경 시 카드 딜레이 구현하기 (0) | 2023.04.02 |
접근성을 고려하여 Tab 키 만을 이용해서 작동 구현 (0) | 2023.04.01 |
Router 연결 관련 문제 (0) | 2023.03.22 |
네비게이션 메뉴 카테고리에서 하위메뉴 띄우기 (0) | 2023.02.01 |