
์ํ ๋ฑ๋ก/์์ ํ์ด์ง์์ ๊ธฐ์กด ์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ๋, ์๋ฌด๋ฐ ๋ก์ง์ ํ์ง์์๋ alert ๊ฒฝ๊ณ ๋ฌธ๊ตฌ๊ฐ ๊ณ์ ๋จ๊ณ ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ๋ค. ์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์จ ํ ํผ์ ์ฑ์ฐ๋ ๊ฐ๋จํ ์์ ์ธ๋ฐ ๊ณ์ํด์ API ํธ์ถ์ด ๋ฐ๋ณต๋๋ฉฐ alert๊ฐ ๋์์์ด ์์ฑ๋์๋ค...
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const productId = searchParams.get('productId');
const { data: productData, error: productError } = useProductDetail(productId);
useEffect(() => {
if (productId && productData) {
handleProductChange(productData);
}
if (productError) {
alert('์์ ํ์ค ์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋๋ฐ ์คํจํ์ต๋๋ค.');
}
}, [productData, productError]);
const {
product,
error,
handleImageChange,
handleProductChange,
handleSubmit,
} = useProductRegistration(onSuccess, productId);
handleProductChange(productData)๋ฅผ ํธ์ถํ๋ฉด product ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ณ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋ค.useEffect(() => {
if (productId && productData) {
handleProductChange(productData);
}
if (productError) {
alert('์์ ํ์ค ์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋๋ฐ ์คํจํ์ต๋๋ค.');
}
}, [productId, productData, productError]);
useEffect(() => {
if (productId && productData && !product.name) {
handleProductChange(productData);
}
if (productError) {
alert('์์ ํ์ค ์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋๋ฐ ์คํจํ์ต๋๋ค.');
}
}, [productId, productData, productError, product.name]);
export const useProductDetail = (productId) => {
return useQuery({
queryKey: [QUERY_KEYS.PRODUCT.DETAIL, productId],
queryFn: async () => {
if (!productId) return null;
const { data, error } = await supabase
.from('products')
.select('*')
.eq('id', productId)
.single();
if (error) throw error;
return data;
},
// ๊ธฐ๋ณธ์ ์ผ๋ก productId๊ฐ ์์ ๋๋ง ์คํ
enabled: !!productId
});
};
useEffect(() => {
if (productData) {
handleProductChange(productData);
}
if (productError) {
alert('์ํ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.');
console.error(productError);
}
}, [productData, productError]);
enabled ์ต์
์ ์กฐ๊ฑด๋ถ ๋ฐ์ดํฐ ๋ก๋ฉ์ ๋งค์ฐ ์ ์ฉํ๋ค.React Query์ enabled ์กฐ๊ฑด์์ ์ฃผ์ํ ์ :
// ์ด๋ ๊ฒ ํ๋ฉด ์ค๋ฅ ๋ฐ์!
enabled: !!productId && !productData.name
productData๊ฐ ์ด๊ธฐ์ undefined์ผ ๋ .name์ ์ ๊ทผํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
onSuccess ์ฝ๋ฐฑ ํ์ฉ:
const { data } = useQuery('products', fetchProducts, {
onSuccess: (data) => {
// ๋ฐ์ดํฐ ๋ก๋ ์ฑ๊ณต ์ ํ ๋ฒ๋ง ์คํ
handleDataLoaded(data);
}
});
์์กด์ฑ ๋ฐฐ์ด์ ๊ฐ์ฒด ํ๋กํผํฐ ๋์ ๊ฐ์ฒด ์์ฒด๋ฅผ ์ฌ์ฉ:
// ์ด๋ ๊ฒ ํ๋ ๊ฒ๋ณด๋ค
}, [product.name]);
// ์ด๋ ๊ฒ ํ๋ ๊ฒ์ด ๋ ์์ ํ ์ ์์
}, [product]);
ํ์ง๋ง ๋ถํ์ํ ๋ ๋๋ง์ด ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
useEffect(() => {
if (!sendAddress) return;
const searchAddress = async (address) => {
try {
const coords = await addressToCoords(address);
// ...๋๋จธ์ง ์ฝ๋
} catch (error) {
// ...์๋ฌ ์ฒ๋ฆฌ
}
};
searchAddress(sendAddress);
}, [sendAddress, addressToCoords, coordsToAddress, onLocationSelect]);
์ด ์ฝ๋๋ฅผ ์์ฑํ๋ค ๋ฌธ๋ ํท๊ฐ๋ ธ๋ค. ํจ์๋ฅผ ์์กด์ฑ ๋ฐฐ์ด์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ณ์ ๋ฐฉํฅ์ด์์๊น?
์นด์นด์ค ๋งต์์ ์ฌ์ฉ์๊ฐ ์ ํํ ๋๋ง๋ค ๊ฐ์ ๋ณํ(๊ฒฝ๋ ์๋ <-> ์ฃผ์๋ช
)ํ์ฌ ๋ณด์ฌ์ค์ผํ๋ ๋ก์ง์ด๊ธฐ์ ํจ์๋ฅผ ์์กด์ฑ ๋ฐฐ์ด๋ก ์ถ๊ฐํ๊ฑด๋ฐ.. ๊ณผ์ฐ ์ณ์์๊น?
์ฐ์ .
ํจ์๋ฅผ useEffect์ ์์กด์ฑ ๋ฐฐ์ด์ ํฌํจ์์ผ์ผ ํ๋ ์ด์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ํจ์๊ฐ ์ผ๊ธ ๊ฐ์ฒด(First-class Object)์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ๋๋ค:
ํจ์๋ ์ซ์, ๋ฌธ์์ด, ๊ฐ์ฒด, ๋ฐฐ์ด์ฒ๋ผ ๊ฐ์ผ๋ก ์ทจ๊ธ๋๋ค.
์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋๋ง๋ค ํจ์๋ ์๋กญ๊ฒ ์์ฑ๋์ด ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ๋ฅผ ๊ฐ๊ฒ ๋๋ค
ํจ์ ๋ด๋ถ์์ ์ฐธ์กฐํ๋ ์ํ๋ props๊ฐ ๋ณ๊ฒฝ๋๋ฉด ํจ์์ ๋์๋ ๋ณ๊ฒฝ ๋ ์ ์๋ค.
ํจ์ ์ ์ธ์ ๋ณ์ ์ ์ธ๊ณผ ๋น์ทํ๊ฒ ์๋ํ๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค:
(updateData !== previousUpdateData)function Component() {
const [count, setCount] = useState(0);
// ์ด ํจ์๋ ๋งค ๋ ๋๋ง๋ง๋ค ์๋ก ์์ฑ๋จ
const updateData = () => {
// count ๊ฐ์ ๋ฐ๋ผ ๋์์ด ๋ฌ๋ผ์ง
fetchData(count);
};
useEffect(() => {
updateData();
}, [updateData]); // updateData๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค effect ์คํ
}
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด useCallback์ ์ฌ์ฉํ๋ฉด ํจ์ ์ฐธ์กฐ์ ์์ ์ฑ์ ํ๋ณดํ ์ ์๊ฒ ๋๋ค.
function Component() {
const [count, setCount] = useState(0);
// count๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์๋ก์ด ํจ์ ์์ฑ
const updateData = useCallback(() => {
fetchData(count);
}, [count]);
useEffect(() => {
updateData();
}, [updateData]);
}
๋ฐ๋ผ์ useEffect ์์กด์ฑ ๋ฐฐ์ด์ ํจ์๋ฅผ ํฌํจ์ํค๋ ๊ฒ์ ํจ์์ ์ฐธ์กฐ๋ ๋ด๋ถ ๋ก์ง์ด ๋ณ๊ฒฝ๋ ๋ effect๋ฅผ ์ฌ์คํํ๋๋ก ํ๊ฒํ๋ ๋ฉ์ปค๋์ฆ์ธ๊ฒ์ด๋ค.
useEffect(() => {
if (!sendAddress) return;
const searchAddress = async (address) => {
try {
const coords = await addressToCoords(address);
// ...๋๋จธ์ง ์ฝ๋
} catch (error) {
// ...์๋ฌ ์ฒ๋ฆฌ
}
};
searchAddress(sendAddress);
}, [sendAddress, addressToCoords, coordsToAddress, onLocationSelect]);
๋ค์ ๋์์์ ๊ทธ๋ผ ๋จผ์ ์ฝ๋์ ๋ชฉ์ ์ ์ ๋ฆฌํด๋ณด๋ฉด
๊ฒฐ๋ก : ์์กด์ฑ ๋ฐฐ์ด์ ํจ์๋ค์ ํฌํจ์ํจ ๊ฒ์ ์ฌ๋ฐ๋ฅธ ์ ๊ทผ์ด์๋ค. ๊ทธ ์ด์ ๋?
addressToCoords์ coordsToAddress๋ ์ง์ค์ฝ๋ฉ ๊ธฐ๋ฅ์ ์ํํ๋ ํจ์๋ก, ๋ด๋ถ ๋ก์ง์ด๋ ์ฐธ์กฐ๊ฐ ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ์์
onLocationSelect๋ ์ ํํ ์์น ์ ๋ณด๋ฅผ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์ ๋ฌํ๋ ์ฝ๋ฐฑ ํจ์๋ก, ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋ฉด ์ ํจ์ ์ฐธ์กฐ๊ฐ ์ ๋ฌ๋ ์ ์๊ธฐ์..