Zustand 곰탱이 귀엽다😆
프로젝트의 메뉴부분의 형태가 다 잡혀서 이제 클릭했을 때 상태마다 보여주는 컴포넌트를 다르게 하기 위해 Zustand를 사용해서 상태관리를 해보려고 한다.
yarn add zustand
위 명령어로 zustand
를 간단하게 설치 가능하다.
zustand는 타입스크립트로 작성된 라이브러리이기 때문에 @types와 같은 추가적인 라이브러리의 설치가 불필요하다.
나는 src
안에 store
라는 폴더를 하나 더 생성하고 그 안에 store.ts
와 types.ts
파일을 생성해서 관리했다.
// store.ts
import { create } from "zustand";
import { MenuStoreType } from "@/store/types";
export const useMenuStore = create<MenuStoreType>((set) => ({
currentMenu: "Home",
setCurrentMenu: (newState) => {
set(() => ({ currentMenu: newState }));
},
}));
기본적인 사용법으로 먼저 create
함수를 이용해 store
를 생성했다.
Redux
와는 달리 providers
로 감싸주지 않아도 사용이 가능하다. 그리고 Recoil
과는 다르게 매개변수인 set
을 받는데 블로그들에 이 부분에 대한 설명이 없어서 zustand 공식 문서에서 더 찾아봤다.
set
함수는 zustand
에서 제공하는 함수라고 한다. set
함수는 함수형 업데이트를 사용한다고 하는데, 여기서 함수형 업데이트란 React
에서 상태 업데이트를 위한 기술 중 하나라고 한다. React에서 상태를 업데이트할 때 setState
함수를 사용하는데, 이 함수는 두 가지 형태로 사용할 수 있다.
첫 번째 형태는 객체를 인자로 받는 방식이다. 이 경우, 객체의 속성과 값이 새로운 상태로 업데이트 된다.
this.setState({ count: 1 })
이 코드는 count
속성의 값을 1로 업데이트 한다.
두 번째 형태는 함수를 인자로 받는 방식이다. 이 경우, 이전 상태를 나타내는 인자와 새로운 값을 반환하는 함수를 전달한다. 반환된 값은 새로운 상태로 업데이트 된다.
this.setState((prevState) => {
return { count: prevState.count + 1}
})
이 코드는 이전 상태를 나타내는 prevState
를 인자로 받고, count
속성을 1증가시킨 값을 반환한다. 반환된 값이 새로운 상태로 업데이트된다.
함수형 업데이트를 사용하면 이전 상태를 기반으로 새로운 상태를 계산할 수 있다. 이전 상태가 함수 내부에서 사용되기 때문에,
setState
함수를 연속해서 호출하는 경우 이전 호출에서 업데이트된 상태를 기반으로 다음 상태를 계산할 수 있다.
zustand
는 set
함수 외에도 여러 유용한 함수를 제공한다고 한다.
사용할 컴포넌트에서 import
하여 다음과 같이 사용할 수 있다.
보기 쉽게 상태관리 관련 코드는 주석을 달아놨다.
import { useMenuStore } from "@/store/store"; // 상태관리 함수 import
import { useState } from "react";
import styled from "styled-components";
interface MenuBtnProps {
menuName: string;
imgURL: string;
selectimgURL: string;
}
const MenuBtn = ({ menuName, imgURL, selectimgURL }: MenuBtnProps) => {
const [isHover, setIsHover] = useState(false);
const { setCurrentMenu } = useMenuStore(); // 상태관리 사용하기
const imgUrl = new URL(imgURL, import.meta.url).href;
const selectedImgUrl = new URL(selectimgURL, import.meta.url).href;
const onMouseOver = () => {
setIsHover(true);
};
const onMouseOut = () => {
setIsHover(false);
};
const onclick = () => {
setCurrentMenu(menuName); // 클릭했을 때 상태 업데이트
};
return (
<MenuBtnStyled
onClick={onclick}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
>
<div>
{isHover ? (
<img src={selectedImgUrl} alt="menu_image" />
) : (
<img src={imgUrl} alt="menu_image" />
)}
</div>
<p className="menu_name">{menuName}</p>
</MenuBtnStyled>
);
};
export default MenuBtn;
useState
처럼 { 상태값, 업데이트함수 } = 함수
형식으로 간편하게 사용할 수 있다. 나는 업데이트 함수만 필요해서 업데이트함수만 선언했다.