npm install zustand
Text.jsx
import React from 'react'
import create from 'zustand';
const useStore = create((set)=>({
fontSize : 14,
increaseFontSize:() => set((state)=>({fontSize:state.fontSize +1}))
}));
export default function Text() {
const fontSize = useStore((state)=> state.fontSize);
const increaseFontSize = useStore((state)=> state.increaseFontSize);
return (
<>
<p style={{fontSize}}>This text will increase in size too.</p>
<button onClick={increaseFontSize}>size up</button>
</>
)
}
set을 create로 만들어 진 값을 업데이트 할 수 있다.
Text.jsx
import React from 'react';
import create from 'zustand';
const useStore = create((set)=>({
fontSize : 14,
increaseFontSize:() => set((state)=>({fontSize:state.fontSize +1})),
trigger:false,
toggleTrigger:()=>set((state)=>({trigger:!state.trigger})),
}));
function FontLabel() {
const{fontSize,increaseFontSize,fontSizeLabel} = useStore((state)=>({
fontSize:state.fontSize,
increaseFontSize:state.increaseFontSize,
fontSizeLabel:state.fontSize + "px",
}))
return (
<>
<div style={{fontSize}}>Current font size: {fontSizeLabel}</div>
<button onClick={increaseFontSize}>size up</button>
</>
)
}
export default function Text() {
const fontSize = useStore((state)=> state.fontSize);
return (
<>
<p style={{fontSize}}>This text will increase in size too.</p>
<FontLabel/>
</>
)
}
2가지 컴포넌트가 분리 되어 있지만 두가지의 state가 연결되어잇는 것을 볼 수 있다.
import React from 'react';
import create from 'zustand';
const useStore = create((set)=>({
fontSize : 14,
increaseFontSize:() => set((state)=>({fontSize:state.fontSize +1})),
trigger:false,
toggleTrigger:()=>set((state)=>({trigger:!state.trigger})),
}));
function FontLabel() {
const{fontSize,increaseFontSize,fontSizeLabel,trigger,toggleTrigger} =
useStore((state)=>({
fontSize:state.fontSize,
increaseFontSize:state.increaseFontSize,
fontSizeLabel:state.fontSize + "px",
trigger:state.trigger,
toggleTrigger:state.toggleTrigger,
}),
(oldState,newState)=>oldState.trigger === newState.trigger)
return (
<>
<div style={{fontSize}}>Current font size: {fontSizeLabel}</div>
<button onClick={increaseFontSize}>size up</button>
<button onClick={toggleTrigger}>toggle: {trigger.toString()}</button>
</>
)
}
export default function Text() {
const fontSize = useStore((state)=> state.fontSize);
return (
<>
<p style={{fontSize}}>This text will increase in size too.</p>
<FontLabel/>
</>
)
}
useStore에 2번째로 인자로 비교 함수를 넣어서 업데이트에 관련된 state를 관리할 수 있다.
sizeup을 누르면 text의 크기가 변하지만 밑에 text의 px값을 변하지 않는다. 하지만
trigger를 통해 trigger가 변경이 일어 났을때 (즉,toggle버튼을 true로 바꿈으로써) 밑에 px의 값이 변한 것을 알 수 있다.
CharacterCount.jsx
import React from 'react'
import create from 'zustand';
const useStore = create((set)=>({
textState:"",
setTextState:(text)=>set(()=>({textState:text})),
}))
export default function CharacterCounter() {
return (
<div>
<TextInput/>
<CharacterCount/>
</div>
)
}
function TextInput(){
const [text,setText] = useStore((state)=>[
state.textState,
state.setTextState,
]);
const onChange = (event) =>{
setText(event.target.value);
}
return(
<div>
<input type="text" value={text} onChange={onChange}/>
<br/>
Echo:{text}
</div>
)
}
function CharacterCount(){
const count = useStore((state)=>state.textState.length);
return <>Character Count:{count}</>
}
import create from "zustand";
import { devtools } from "zustand/middleware";
export const useStore = create(
devtools((set, get) => ({
todoListState: [],
setTodoListState: (list) => set({ todoListState: list }),
todoListFilterState: "Show All",
settodoListFilterState: (filter) => set({ todoListFilterState: filter }),
filteredTodoListState: () => {
const filter = get().todoListFilterState;
const list = get().todoListState;
switch (filter) {
case "Show Completed":
return list.filter((item) => item.isComplete);
case "Show Uncompleted":
return list.filter((item) => !item.isComplete);
default:
return list;
}
},
todoListStatsState: () => {
const todoList = get().todoListState;
const totalNum = todoList.length;
const totalCompletedNum = todoList.filter(
(item) => item.isComplete
).length;
const totalUncompletedNum = totalNum - totalCompletedNum;
const percentCompleted =
totalNum === 0 ? 0 : totalCompletedNum / totalNum;
return {
totalNum,
totalCompletedNum,
totalUncompletedNum,
percentCompleted,
};
},
}))
);
useStore뒤에 devtools 선언후 ()를 감싸주면 됨.
redux-devtools로 상태값들을 확인할 수 있다.
import axios from 'axios';
import React from 'react'
import { useEffect } from 'react';
import create from 'zustand';
const useStore = create((set,get)=>({
id:2,
setId:(id) =>set({id:id}),
userName:"park",
fetchUserName:async()=>{
const response = await axios.get(
`/api/user-name?id=${get().id}`
);
set({useName:response.data.name});
}
}))
function CurrentUser() {
const userName = useStore(state=>state.useName);
return <div>{userName}</div>;
}
export default function CureentUserInfo(){
const [id, setId] = useStore(state=>[state.id,state.setId]);
const fetchUserName = useStore(state=>state.fetchUserName);
useEffect(()=>{
fetchUserName();
},[id])
return (
<>
<CurrentUser/>
<input value={id} onChange={(e)=>setId(e.target.value)}/>
</>
)
}