zustand useshallow는 언제쓸까?

2023. 11. 19. 14:55·⭐FE

기본적인 Zustand store 구독 방법

import { create } from 'zustand'

// store 생성
const useStore = create((set) => ({
    a:"a",
    b:"b",
    c:"c",
    d:"d",
}))

const Coponent = ()=>{
	// a,b,c,d state 구독
    const a = useStore((state)=> state.a)
    const b =useStore((state)=> state.b)
    const c =useStore((state)=> state.c)
    const d =useStore((state)=> state.d)

    return(
    <>
        <p>a:{a} </p>
        <p>b:{b} </p>
        <p>c:{c} </p>
        <p>d:{d} </p>
    </>
    )
}

 

Zustand를 사용할 때 store의 여러 state를 구독 할때 위 코드내 13~16번째 줄 처럼같이 일일히 하나씩 받아옵니다. 하지만 만 뭔가 좀 무식해 보이지 않나요?

여러 State를 세련된(?)방법으로 store 구독 하려면 useShallow를 사용하자

	// a,b,c,d state 구독
    const [a,b,c,d] = useStore((state)=> ([state.a, state.b, sate.c, state.d]))

그래서 위와 같이 한번에 가져 올 수 있습니다. 하지만 이렇게 한번에 가져올 시 문제가 생깁니다. 어떤 문제가 생기냐면 다른 컴포넌트에서 위와 같은 방식으로 여러 state를 구독했을 시 불필요한 리렌더링이 발 생 할 수 있습니다. 

import { useEffect } from 'react'
import { create } from 'zustand'

const useStore = create((set) => ({
    a:"a",
    b:"b",
    c:"c",
    setA:()=>set((state)=>({a:state.a})),
}))

export const Parent =() =>{
    return (
        <>
            <Child1></Child1>
            <Child2></Child2>
        </>
    )
}


const Child1 = ()=>{
    const [a, setA] = useStore((state)=>( [state.a, state.setA]))
    useEffect(()=>{
        console.log("<Child1> 렌더링");
    })
    return(<button onClick={()=>{
        console.log("버튼클릭됨");
        setA()
    }}>child1</button>) // 버튼 클릭시     
}

const Child2 = ()=>{
    const [b,c] = useStore((state)=>([state.b,state.c]))
    useEffect(()=>{
        console.log("<Child2> 렌더링");
    })
    return(<p>child2</p>)
}

위 코드의 <Child1> 컴포넌트 내부에 button을 클릭시 store의 state 값 a가 변경됩니다. 그래서 a를 구독하고 있는 <Child1> 컴포넌트만 렌더링 될 것으로 예상되지만 실제로는 a를 구독하고 있지 않은 <Child2>의 컴포넌트도 렌더링이 됩니다. 이상하죠? 공식문서에서는 불필요한 리렌더링을 막기 위해 useShallow를 쓰라고 권장합니다. 

import { useShallow } from 'zustand/react/shallow'
...

const Child1 = ()=>{
	// useShallow로 감쌈
    const [a, setA] = useStore(useShallow((state)=>( [state.a, state.setA])))
    useEffect(()=>{
        console.log("<Child1> 렌더링");
    })
    return(<button onClick={()=>{
        console.log("버튼클릭됨");
        setA()
    }}>child1</button>) // 버튼 클릭시     
}

const Child2 = ()=>{
	// useShallow로 감쌈
    const [b,c] = useStore(useShallow((state)=>([state.b,state.c])))
    useEffect(()=>{
        console.log("<Child2> 렌더링");
    })
    return(<p>child2</p>)
}

 

요렇게 state를 가져올 때 useShallow로 가져 올 시 구독하지 않은 state가 변하지 않을 경우 재렌더링은 일어나지 않습니다. 물론 맨위에서 일일히 state를 가져오는 방법을 사용할 시 굳이 useShallow는 사용하지 않아도 리렌더링 문제는 발생하지 않습니다. 

 

참고

https://github.com/pmndrs/zustand

https://zustand-demo.pmnd.rs/

'⭐FE' 카테고리의 다른 글

Object.is() 개념잡기  (0) 2023.11.21
React useState 호출 시 무조건 렌더링 된다?  (0) 2023.11.19
useMemo 이해하기  (0) 2023.11.19
storybook 파악하기  (0) 2023.09.17
[Typescript] Typescript 환경을 구성해보자  (0) 2022.07.10
'⭐FE' 카테고리의 다른 글
  • Object.is() 개념잡기
  • React useState 호출 시 무조건 렌더링 된다?
  • useMemo 이해하기
  • storybook 파악하기
devWarrior
devWarrior
  • devWarrior
    devWarrior
    devWarrior
  • 전체
    오늘
    어제
    • 🧩Dev (263)
      • ⭐FE (34)
      • 🔒Algorithm (155)
      • ➕Etc. (11)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    dp
    구현
    자바스크립트
    코테
    Algorithm
    실버1
    leetcode
    알고리즘
    DFS
    티스토리챌린지
    javascript
    자스
    nodejs
    실버3
    골드5
    Easy
    node.js
    프론트엔드
    코딩테스트
    그리디
    js
    BFS
    실버2
    실버4
    Lv2
    FE
    프로그래머스
    백준
    react
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
devWarrior
zustand useshallow는 언제쓸까?
상단으로

티스토리툴바