//ReviewForm.js
import { createReview } from '../api';
const INITIAL_VALUES = {
title: '',
rating: 0,
content: '',
imgFile: null,
};
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('title', values.title);
formData.append('rating', values.rating);
formData.append('content', values.content);
formData.append('imgFile', values.imgFile);
try {
setSubmittingError(null);
setIsSubmitting(true);
await createReview(formData);
} catch (error) {
setSubmittingError(error);
return;
} finally {
setIsSubmitting(false);
}
setValues(INITIAL_VALUES);
};
<button disabled={isSubmitting} type="submit">
확인
</button>
{submittingError && <div>{submittingError.message}</div>}
//api.js
export async function createReview(formData) {
const response = await fetch(`${BASE_URL}/film-reviews`, {
method: 'POST',
body: formData,
});
if (!response.ok) {
throw new Error('리뷰를 생성하는데 실패했습니다.');
}
const body = await response.json();
return body;
fetch함수에서 Post를 할 때 formData로 하는 게 좋은가 보다.
const handleLoad = useCallback((option) => {
// ...
}, [dep1, dep2, dep3, ...]);
함수를 매번 새로 생성하는 것이 아니라 디펜던시 리스트가 변경될 때만 함수를 생성
하위 컴포넌트에서 어떤 state를 쓰고 싶은데 이를 위해선 상위 컴포넌트에서 prop으로 계속 내려줘야 한다.
그걸 방지하고 전역적으로 쓸 수 있는 변수 생성을 위해 Context를 만들었다.
많은 컴포넌트에서 사용하는 데이터를 반복적인 prop 전달 없이 공유하는 것.
Context 사용시에는 반드시 사용 범위를 설정하고 써야한다. 이때 범위는 Provider라는 컴포넌트로 설정할 수 있다.
createContext라는 리액트 함수로 Context를 만들 수 있다.
import { createContext } from 'react';
const LocaleContext = createContext('ko');
function App() {
return (
<div>
... 바깥의 컴포넌트에서는 LocaleContext 사용불가
<LocaleContext.Provider value="en">
... Provider 안의 컴포넌트에서는 LocaleContext 사용가능
</LocaleContext.Provider>
</div>
);
}
useContext라는 Hook을 통해 Context를 사용한다. 아규먼트로 사용할 Context를 넘기자.
import { createContext, useContext } from 'react';
const LocaleContext = createContext('ko');
function Board() {
const locale = useContext(LocaleContext);
return <div>언어: {locale}</div>;
}
function App() {
return (
<div>
<LocaleContext.Provider value="en">
<Board />
</LocaleContext.Provider>
</div>
);
}
공유 범위를 설정하는 Provider 컴포넌트를 따로 하나 만들고, state를 만들어 value로 넘겨준다.
그럼 이제 value 안에 값들이 Context에 담기는데, 이를 이용해서 useLocale,useSetLocale처럼 custom hook을 만들 수도 있다.
import { createContext, useContext, useState } from 'react';
const LocaleContext = createContext({});
export function LocaleProvider({ children }) {
const [locale, setLocale] = useState();
return (
<LocaleContext.Provider value={{ locale, setLocale }}>
{children}
</LocaleContext.Provider>
);
}
export function useLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { locale } = context;
return locale;
}
export function useSetLocale() {
const context = useContext(LocaleContext);
if (!context) {
throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
}
const { setLocale } = context;
return setLocale;
}
}