|
const handleInput = (event) => { |
|
const { value } = event.target; |
|
if (value.length <= 3000) { |
|
adjustTextareaHeight(); |
|
} |
|
}; |
|
|
|
const adjustTextareaHeight = () => { |
|
if (textareaRef.current) { |
|
const minHeight = 50; |
|
textareaRef.current.style.height = 'auto'; |
|
const scrollHeight = textareaRef.current.scrollHeight; |
|
if (scrollHeight >= minHeight) { |
|
textareaRef.current.style.height = `${scrollHeight + 4}px`; |
|
} |
|
} |
|
}; |
|
|
|
const handleFileChange = (event) => { |
|
const selectedFile = event.target.files[0]; |
|
setFile(selectedFile); |
|
setPreviewUrl(URL.createObjectURL(selectedFile)); |
|
}; |
|
|
|
const handleUploadAndSubmit = async () => { |
|
try { |
|
setUploading(true); |
|
let imageUrl = null; |
|
if (textareaRef.current.value === '') { |
|
alert('내용을 입력해주세요.'); |
|
setUploading(false); |
|
return; |
|
} |
|
|
|
if (file) { |
|
const fileExt = file.name.split('.').pop(); |
|
const fileName = `${Date.now()}.${fileExt}`; |
|
const filePath = `public/${fileName}`; |
|
|
|
let { error: uploadError } = await supabase.storage |
|
.from('images') |
|
.upload(filePath, file, { |
|
cacheControl: '3600', |
|
upsert: false, |
|
}); |
|
|
|
if (uploadError) { |
|
throw uploadError; |
|
} |
|
|
|
const publicUrl = supabase.storage |
|
.from('images') |
|
.getPublicUrl(filePath); |
|
|
|
imageUrl = publicUrl.data.publicUrl; |
|
setPreviewUrl(null); |
|
setFile(null); |
|
} |
|
|
|
const { data, error } = await supabase |
|
.from('reviews') |
|
.insert([ |
|
{ |
|
product_id: productId, |
|
username: user.email, |
|
review_text: textareaRef.current.value.trim(), |
|
review_img: imageUrl, |
|
}, |
|
]) |
|
.select(); |
|
|
|
if (error) { |
|
return; |
|
} else { |
|
setReviewList([...reviewList, ...data]); |
|
textareaRef.current.value = ''; |
|
} |
|
} catch (error) { |
|
alert('Error uploading image and submitting review!'); |
|
} finally { |
|
setUploading(false); |
|
} |
|
}; |
|
|
|
const handleCancelSelection = () => { |
|
setPreviewUrl(null); |
|
setFile(null); |
|
}; |
uploadImg state는 사용하지 않고 있는데, 왜 선언했나요?
mission/0617/src/page/detail/index.jsx
Line 47 in 5459245
상관은 없지만 다른 페이지 혹은 컴포넌트에서 상품 상세, 리뷰들을 API로 가져오는 코드를 사용할 땐 setProductDetail, setReveiwList 때문에 재사용을 못할 수도 있을 것 같습니다. API를 가져오는 기능 이외에 state도 변경시키기는 두 가지 역할을 하고 있네요.
mission/0617/src/page/detail/index.jsx
Lines 12 to 36 in 5459245
이 state는 여기가 아니라 ReviewList 컴포넌트 안에서 선언해도 되지 않을까요? index.js 파일의 코드에 상품 정보와 리뷰 정보가 함께 있어 코드를 읽기가 불편한 것 같습니다.
mission/0617/src/page/detail/index.jsx
Line 44 in 5459245
3번에서 말한 것처럼 이 코드들은 전체 다 ReviewList에 들어가는 게 맞을 것 같습니다.
mission/0617/src/page/detail/index.jsx
Lines 54 to 141 in 5459245