//////////////////////////////////////////////////////////////////////////////////
// store.ts
//////////////////////////////////////////////////////////////////////////////////
import { create } from 'zustand'; export interface Post { id: number; title: string; body: string; } interface PostStore { searchQuery: string; setSearchQuery: (query: string) => void; } export const usePostStore = create<PostStore>((set) => ({ searchQuery: '', setSearchQuery: (query) => set({ searchQuery: query }), })); //////////////////////////////////////////////////////////////////////////////////
// api.ts
////////////////////////////////////////////////////////////////////////////////// import axios from 'axios'; import { useQuery } from '@tanstack/react-query'; import { Post } from './store'; const fetchPosts = async (): Promise<Post[]> => { const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts'); return data; }; export const usePosts = () => { return useQuery<Post[], Error>({ queryKey: ['posts'], queryFn: fetchPosts, }); };
//////////////////////////////////////////////////////////////////////////////////
// PostList.tsx ////////////////////////////////////////////////////////////////////////////////// import { useState, useEffect } from 'react'; import { usePosts } from './api'; import { usePostStore } from './store'; const PostList: React.FC = () => { // A. useState: 로컬 UI 상태 (입력값 등) const [localTitle, setLocalTitle] = useState<string>("");
// B. Zustand: 전역 상태 가져오기 const { searchQuery, setSearchQuery } = usePostStore();
// C. React Query: 서버 데이터 가져오기 const { data: posts, isLoading, isError, error } = usePosts();
// D. useEffect: 검색어가 바뀔 때마다 로그 출력 (예시) useEffect(() => { if (searchQuery) { console.log(`검색어 변경됨: ${searchQuery}`); } }, [searchQuery]);
if (isLoading) return <div>로딩 중...</div>;
if (isError) return <div>에러 발생: {error.message}</div>;
return ( <div style=> <h1>포스트 목록</h1> {/* 로컬 상태 조작 */} <input type="text" value={localTitle} onChange={(e) => setLocalTitle(e.target.value)} placeholder="로컬 타이틀 입력" /> {/* 전역 상태 조작 (Zustand) */} <button onClick={() => setSearchQuery(localTitle)}> 전역 검색어 설정 </button> <p>현재 검색어: {searchQuery}</p> <ul> {posts?.filter(p => p.title.includes(searchQuery)).map((post) => ( <li key={post.id}> <strong>{post.title}</strong> </li> ))} </ul> </div> ); }; export default PostList;
자바 해보면 interface 까지는 익숙해지는데 도저히 저거 이벤트마다 타입 넣는건 너무 번거로움
Promise 객체도 자바의 제너릭 타입처럼 예상되는 반환 타입 인터페이스로 정의 해줘야하네
외울게 늘어나서 힘들다 프론트 하는 사람들 새삼 대단해 MZ하게 매번 새로운게 쏟아져나옴
원래 프론트쪽은 JQuery만 알다가 SPA 프레임워크 입문을 리액트로 시작해서 react-router-dom, zustand, react-query 까지만 알려하다가 하고 싶은게 있어서 어쩌다보니 타입스크립트까지 건들게 되네 난 Vue, Angular, Svelte는 못쓰겠고 Next.js 까지만 공부해야할듯
