
tsrafce
<typescript />
import React from 'react'
type Props = {}
const page = (props: Props) => {
return (
<div>page</div>
)
}
export default page
usf
<typescript />
const [, set] = useState();
uef
<typescript />
useEffect(() => {
}, []);
ZUSTAND 설치법
<typescript />yarn add zustand
/src/app/zustand 폴더 생성 후 page.tsx 생성
<typescript />
import { create } from 'zustand'
type Props = {}
interface TestStore {
count: number;
increment: () => void;
decrement: () => void;
}
//zustand는 전역 상태 관리 라이브러리
const useTestStore = create<TestStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 }))
}));
export default useTestStore
<typescript />
import { create } from 'zustand'
type Props = {}
interface TestStore {
count: number;
increment: () => void;
decrement: () => void;
}
//zustand는 전역 상태 관리 라이브러리
const useTestStore = create<TestStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 }))
}));
const ZustandTestPage = (props: Props) => {
const { count, increment, decrement } = useTestStore();
//useShallow로 사용하는 방법 찾아서 적용해보기
//useShallow 쓰는 이유 찾아보기
return (
<div className="flex gap-2 items-center">
<div>{count}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
export default ZustandTestPage;
useShallow 사용!!
<typescript />
import { create } from 'zustand'
import { shallow } from 'zustand/shallow'
type Props = {}
interface TestStore {
count: number;
increment: () => void;
decrement: () => void;
}
//zustand는 전역 상태 관리 라이브러리
const useTestStore = create<TestStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 }))
}));
const ZustandTestPage = () => {
// useShallow를 사용하는 방법 1: 객체 선택자와 함께 사용
// const { count, increment, decrement } = useTestStore(
// (state) => ({
// count: state.count,
// increment: state.increment,
// decrement: state.decrement
// }),
// shallow
// );
// useShallow를 사용하는 방법 2: 개별 선택자 사용 (권장)
const count = useTestStore((state) => state.count);
const increment = useTestStore((state) => state.increment);
const decrement = useTestStore((state) => state.decrement);
return (
<div className="flex gap-2 items-center">
<div>{count}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
export default ZustandTestPage;
useShallow를 쓰는 이유
1. 불필요한 리렌더링 방지
- 매번 새로운 객체가 생성되어 리렌더링 발생
- 얕은 비교를 통해 실제 값이 변경되었을 때만 리렌더링
2. 성능 최적화
- 객체의 얕은 비교를 수행
- 실제로 값이 변경되었을 때만 리렌더링
- 메모리 사용량 감소
3. 메모리 효율성
-불필요한 객체 생성 방지
- 가비지 컬렉션 부하 감소
4. 예측 가능한 동작
- 상태 업데이트 시 컴포넌트의 리렌더링 시점을 더 정확하게 제어 가능
- 디버깅이 용이
터미널에 아래 코드 쳐서 다운로드 했습니다.
<typescript />yarn add zod
<typescript />yarn add react-hook-form
아예 싹 지우고 다시 작성함
<typescript />
'use client'
import { create } from 'zustand'
import { shallow } from 'zustand/shallow'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
const ZodTestPage = () => {
const schema = z.object({
name: z.string().min(1, "이름은 2글자 이상으로 적어주세요"),
email: z.string().email("이메일 양식이 올바르지 않습니다."),
});
const form = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
defaultValues: {
name: "",
email: "",
}
});
const onSubmit = (values: z.infer<typeof schema>) => {
console.log(values);
};
return (
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-2 p-4">
<input
type='text'
{...form.register("name")}
placeholder="이름"
className="border p-2 rounded"
/>
{form.formState.errors.name && (
<p className="text-red-500">{form.formState.errors.name.message}</p>
)}
<input
type='text'
{...form.register("email")}
placeholder="이메일"
className="border p-2 rounded"
/>
{form.formState.errors.email && (
<p className="text-red-500">{form.formState.errors.email.message}</p>
)}
<button
type='submit'
className="bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
>
제출
</button>
</form>
);
}
export default ZodTestPage;