> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/state-management/zustand.md).

# Zustand

## Zustand

```bash
npm install zustand
```

* 'zustand'는 독일어로 'state'라는 뜻한다.
* 간소화된 Flux 원칙을 따르며 작고 확장 가능한 최소한의 상태 관리 솔루션
* Redux와 굉장히 유사하지만 개발자가 상태를 처리하기 위해 Reducer, Actions, Dispatch를 만들어야하는 Redux와 달리 Zustand는 굉장히 간단하다.
* Hooks를 사용하여 상태를 관리

### 장점

* Boiler plate 코드가 굉장히 적다.
* Context Provider를 사용할 필요가 없어 더욱 간단해지고 가독성이 높아진다.

### Store 생성하기

* Store는 Hooks으로 되어있으며, Store 안에는 객체, 함수 등 무엇이든 넣을 수 있다.
* 제공되는 `create` 함수를 사용하여 Store를 생성
* `set` 함수를 통해 상태를 변경한다.&#x20;

```jsx
import create from 'zustand';

export const useCounterStore = create((set) => ({
  count: 1,
  increase: () => set((state) => ({ count: state.count + 1 }))
}))
```

```jsx
import { useCounterStore } from '@/store';

export const Counter = () => {
  const { count, increase } = useCounterStore();
  
  return (
    <button type="button" onClick={increase}>{count}</button>
  )
}
```

### Persist Middleware

> 상태를 local storage에 저장하여 새로고침 해도 값을 유지하도록 설정해보자.

```jsx
import create from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';

export const useCounterStore = create(
  persist((set) => ({
    count: 1,
    increase: () => set((state) => ({ count: state.count + 1 }))
  }),
  { 
    name: 'counter'
    storage: createJSONStorage(() => sessionStorage)
  })
)
```

#### Persist Options

* **name**: local storage key값을 지정
* **storage**: 저장할 스토리지를 지정해줄 수 있다. (로컬 스토리지, 세션 스토리지)
  * default -> `createJSONStorage(() => localStorage)`
* **partialize** -> 저장할 상태의 일부만을 스토리지에 관리할지 설정할 수 있다.
* **onRehydrationStorage** -> 스토리지가 수화될 때 호출될 콜백함수를 지정
* **merge** -> 미들웨어는 기본적으로 얕은 병합을 수행, 해당 함수를 사용하여 깊은 병합을 수행할 수 있다.
* **skipHydration** -> 기본적으로 초기화시 hydration이 실행되는데 특정 상황의 경우 첫 hydration 시기를 제어하고 싶을 때 사용한다. 단, 수동으로 `rehydrate()`를 실행시켜주어야 한다.

### DevTools

> Zustand는 [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko)를 사용할 수 있다.

```jsx
import create from 'zustand';
import { devtools } from 'zustand/middleware';

export const useCounterStore = create(
  devtools((set) => ({
    count: 1,
    increase: () => set((state) => ({ count: state.count + 1 }))
  }), 
)

/**
let counterStore = (set) => ({
  count: 1,
  increase: () => set((state) => ({ count: state.count + 1 }))
});

counterStore = devtools(counterStore);
counterStore = persist(counterStore, { name: 'counter' });

export const useCounterStore = create(counterStore) 
**/
```

### Async

> zustand는 작업이 동기인지 비동기인지 신경쓰지 않는다.  \
> 상태를 변경하는 `set` 함수를 호출하기만 하면 된다.

```jsx
const useStore = create((set) => ({
  item: {},
  fetch: async (pond) => {
    const response = await axios.get('/foo');
    set({ item: response.data }) 
  }
}))
```
