# 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 }) 
  }
}))
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/state-management/zustand.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
