내가 맡은 부분은 작성폼 페이지이다! 오늘은 작성폼 페이지 기능구현에 대해서 블로그를 써보겠다.
1. 상태 관리
일단 상태관리는 useState 훅을 사용하여 폼데이터를 관리한다. 각 입력 필드에 대한 상태를 하나의 객체로 관리하고 있다.
const [formData, setFormData] = useState({
storeName: '',
image: null,
address: '',
region: '',
rating: '',
review: ''
});
2. Context 사용
PostContext를 통해 전역 상태를 관리하고 있다. 이를 통해 게시물 목록을 업데이트할 수 있다.
const { posts, setPosts } = useContext(PostContext);
3. 이벤트 핸들러
입력 변경 핸들러: 각 입력 필드의 변경을 감지하고 상태를 업데이트한다.
const handleChange = (e) => {
const { id, value } = e.target;
setFormData((prevData) => ({ ...prevData, [id]: value }));
};
4. 파일 변경 핸들러
이미지 파일 선택 시 상태를 업데이트한다.
const handleFileChange = (e) => {
setFormData((prevData) => ({ ...prevData, image: e.target.files[0] }));
};
5. 폼 제출 처리
handleSubmit 함수에서 폼 제출 처리를 한다.
만약에 이미지 파일이 있으면 Supabase 스토리지에 보내고 없으면 null을 보낸다. 그다음 스토리지에서 이미지의 공개 URL을 가져온다.
그럼 다시 각종 폼 정보를 객체로 받아서 Supabase로 다시 보낸다. 스토어에서 보낼 때, data와 error값을 받는다. data는 업로드가 성공했을 때 반환되는 객체로 업로드된 파일에 대한 메타 데이터를 포함한다. error는 업로드 과정에서 문제가 발생했을 때 반환되는 객체이다. error가 만약있다면 오류 메세지를 띄어주도록 했다.
const handleSubmit = async (e) => {
e.preventDefault();
try {
let imagePath = null;
// 이미지 업로드
if (formData.image) {
const fileName = `store_img_${Date.now()}.png`;
const { error } = await supabase.storage.from('store_img').upload(`public/${fileName}`, formData.image);
if (error) throw error;
// 업로드 된 이미지의 공개 URL 가져오기
imagePath = `${supabase.storage.from('store_img').getPublicUrl(`public/${fileName}`).data.publicUrl}`;
}
const { data, error } = await supabase.from('store').insert({
writer: 'coolcat1',
store_name: formData.storeName,
image: imagePath,
address: formData.address,
location: formData.region,
star: formData.rating,
comment: formData.review
});
console.log('응답값', data);
if (error) throw error;
console.log('게시물이 성공적으로 생성되었습니다', data);
setFormData({
storeName: '',
image: null,
address: '',
region: '',
rating: '',
review: ''
});
alert('게시물이 성공적으로 작성되었습니다!');
} catch (error) {
console.error('게시물 작성 중 오류 발생', error.message);
alert('게시물 작성 중 오류 발생 다시 시도 바란다.');
}
};
6. 기본적인 UI
뼈대 정도만 잡아주었다. 여기서 새로 배운 내용은 <select>이다. 드롭다운 목록의 컨테이너 역할을 한다. <option>는 select 내부에 위치하며, 각각의 선택 가능한 항복을 나타낸다.
return (
<SyFormContainer>
<h2>맛집 게시글 작성</h2>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="storeName">가게 상호명</label>
<input id="storeName" type="text" value={formData.storeName} onChange={handleChange} />
</div>
<div>
<label htmlFor="image">이미지 업로드</label>
<input id="image" type="file" accept="image/*" onChange={handleFileChange} />
</div>
<div>
<label htmlFor="address">주소</label>
<input id="address" type="text" value={formData.address} onChange={handleChange} />
</div>
<div>
<label htmlFor="region">지역</label>
<select id="region" value={formData.region} onChange={handleChange}>
<option value="">선택하세요</option>
<option value="지역1">지역1</option>
<option value="지역2">지역2</option>
<option value="지역3">지역3</option>
<option value="지역4">지역4</option>
<option value="지역5">지역5</option>
</select>
</div>
<div>
<label htmlFor="rating">별점</label>
<select id="rating" value={formData.rating} onChange={handleChange}>
<option value="">선택하세요</option>
<option value="1">1점</option>
<option value="2">2점</option>
<option value="3">3점</option>
<option value="4">4점</option>
<option value="5">5점</option>
</select>
</div>
<div>
<label htmlFor="review">후기</label>
<textarea id="review" rows="5" value={formData.review} onChange={handleChange}></textarea>
</div>
<div>
<button type="submit">게시글 등록</button>
</div>
</form>
{/* <div>
{posts.map((post) => (
<WriteList key={post.id} post={post} />
))}
</div> */}
</SyFormContainer>
);
};
export default WriteFormContainer;
팀프로젝트 시 오류와 해결방안
❌ Supabase 접근 못하는 문제점
- RLS를 비활성화하여 문제 해결
- RLS(Row Level Security)는 supabase에서 제공하는 보안 기능이다.
- 데이터베이스테이블의 각 행(row)에 대한 접근을 제한한다.
- 사용자 권한에 따라 특정 데이터만 읽거나 수정할 수 있도록 제한한다.
- 따라서 RLS를 비활성화하면 모든 사용자가 해당 테이블의 모든 데이터에 접근할 수 있게 된다.
- https://github.com/orgs/supabase/discussions/3780
❌ SupabaseClient에 supabase URL,KEY 값을 불러오지 못하는 오류
- .env.local 로 파일을 만들었는데 키값을 불러오지 못해서 .env로 파일명으로 바꿔주었더니 해결
- .env.local은 로컬 환경에서만 사용되며, 일반적으로 버전 관리에서 제외된다.
- .env는 모든 환경에서 사용되며, 일반적으로 버전 관리에 포함된다.
- 따라서 .env 파일은 모든 환경에서 기본적으로 로드될 수 있어 키값을 불러올 수 있지만 이 파일은 버전 관리 시스템에 포함될 수 있으므로 주의가 필요하다.
'팀프로젝트' 카테고리의 다른 글
맛집 뉴스피드 프로젝트 마무리 및 KPT회고 (10) | 2024.09.04 |
---|---|
맛집 뉴스피드 프로젝트 중간점검 (8) | 2024.09.02 |
리액트 뉴스피드 프로젝트 초기 (5) | 2024.08.28 |
3주차 팀프로젝트를 마치며... (1) | 2024.08.07 |
3주차 팀프로젝트 중간점검 (0) | 2024.08.06 |