Argument of type '(prev: string[]) => string[]' is not assignable to parameter of type 'string[]'
React에서 useState로 상태를 관리하다 보면,
setState 함수를 다른 컴포넌트로 props로 넘겨야 하는 상황이 자주 발생합니다.
그런데 setState를 props로 넘긴 후, 이전 상태 값을 활용해 업데이트하려고 하면 위와 같이 TypeScript 오류가 발생할 수 있습니다.
■ setState를 props로 넘길 때 발생하는 오류
// 부모 컴포넌트
const Parent = () => {
const [user, setUser] = useState<string[]>([]);
return <Child user={user} setUser={setUser} />;
};
// 자식 컴포넌트
const Child = ({ user, setUser }: {
user: string[];
setUser: (user: string[]) => void
}) => {
const handleUpdate = () => {
setUser((prev) => [...prev, "newUser"]); // ❌ 오류 발생!
};
return <button onClick={handleUpdate}>추가</button>;
};
//❌오류 메세지
Argument of type '(prev: string[]) => string[]' is not assignable to parameter of type 'string[]'
✔ setUser의 타입이 (user: string[]) => void로 지정되어 있기 때문에
✔ 이전 상태(prev)를 활용하는 (prev) => [...prev, "newUser"] 방식이 허용되지 않음
그렇다면 어떻게 해결할 수 있을까요?
■ 해결 방법: Dispatch<SetStateAction<T>>
React에서 useState의 타입을 보면 다음과 같습니다.
function useState<T>(initialState: T | (() => T)): [T, Dispatch<SetStateAction<T>>];
즉, useState<string[]>를 사용하면 내부적으로 setState의 타입이 Dispatch<SetStateAction<string[]>>가 됩니다.
그렇다면, SetStateAction<T>란?
type SetStateAction<T> = T | ((prevState: T) => T);
✔ T 값을 직접 설정할 수도 있고,
✔ (prevState: T) => T 형태로 이전 상태를 기반으로 업데이트할 수도 있음
즉, setUser((prev) => [...prev, "newUser"]) 같은 코드를 허용하려면
setState의 타입을 Dispatch<SetStateAction<T>>로 지정해야 합니다.
■ 최종 해결 코드
// 자식 컴포넌트
const Child = ({ user, setUser }: {
user: string[];
setUser: React.Dispatch<React.SetStateAction<string[]>>; // ✅ 올바른 타입 지정
}) => {
const handleUpdate = () => {
setUser((prev) => [...prev, "newUser"]); // ✅ 정상 동작!
};
return <button onClick={handleUpdate}>추가</button>;
};
✔ setUser의 타입을 React.Dispatch<React.SetStateAction<string[]>>로 지정
✔ 이제 setUser(["user1", "user2"])도 가능하고,
✔ setUser((prev) => [...prev, "newUser"])도 정상적으로 동작
■ 그렇다면, 왜 useState<T>처럼 간단하게 쓰지 않을까?
React에서 useState<T>를 사용한다면
const [user, setUser] = useState<string[]>([]);
✔ useState는 자동으로 [T, Dispatch<SetStateAction<T>>] 타입을 반환
✔ setUser의 타입이 Dispatch<SetStateAction<string[]>>로 자동 설정됨
❌ 하지만, React는 props의 타입을 자동으로 추론하지 않기 때문에, setState를 props로 넘길 때는 반드시 Dispatch<SetStateAction<T>>를 명시해야함