각 코드의 비교를 통한 shallow를 알아보려고 한다.
console.log()
로 어느 컴포넌트가 렌더링 되는지 확인 바랍니다
혹시라도 더 정확한 설명을 댓글로라도 알려주시면 감사하겠습니다.
import { create } from "zustand";
import { useShallow } from "zustand/react/shallow";
const useStore = create((set) => ({
name: "John",
age: 30,
address: "123 Main St",
setName: (name) => set({ name }),
setAge: (age) => set({ age }),
setAddress: (address) => set({ address }),
}));
const UserInfo = () => {
const name = useStore((state) => state.name);
const age = useStore((state) => state.age);
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
const Address = () => {
const address = useStore((state) => state.address);
console.log(address);
return <div>Address: {address}</div>;
};
const App = () => {
const setName = useStore((state) => state.setName);
const setAge = useStore((state) => state.setAge);
const setAddress = useStore((state) => state.setAddress);
console.log("app Rendered");
return (
<div>
<UserInfo />
<Address />
<button onClick={() => setName("Jane")}>Change Name</button>
<button onClick={() => setAddress("Wall.St")}>Change Address</button>
<button onClick={() => setAge(31)}>Change Age</button>
</div>
);
};
export default App;
console.log()
결과 찍어보기
changeName
, changeAge
실행userInfo
컴포넌트 리렌더
changeAddress
실행Address
컴포넌트 리렌더
코드량을 줄어들었지만 어떤 일이 생기는지 보자.
//...useStore는 변경점 없음
const UserInfo = () => {
const { name, age } = useStore();
console.log(name);
console.log(age);
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
const Address = () => {
const address = useStore((state) => state.address);
console.log(address);
return <div>Address: {address}</div>;
};
const App = () => {
const { setName, setAge, setAddress } = useStore();
console.log("app Rendered");
return (
<div>
<UserInfo />
<Address />
<button onClick={() => setName("Jane")}>Change Name</button>
<button onClick={() => setAddress("Wall.St")}>Change Address</button>
<button onClick={() => setAge(31)}>Change Age</button>
</div>
);
};
export default App;
changeName
, changeAge
, changeAddress
실행구조 분해 할당으로 빼오면 모든 컴포넌트가 동일하게 리렌더링이 일어남 (권장X)
userInfo
, Address
컴포넌트 리렌더
구조 분해 할당은 안쓰는게 맞는거 확인.
특정 케이스로 쓰는경우는 있겠지만 되도록 안쓰는게 좋아보임
useShallow
를 쓴 코드//... useStore는 변경점 없음
import { useShallow } from "zustand/react/shallow";
const UserInfo = () => {
const { name, age } = useStore(
useShallow((state) => ({ name: state.name, age: state.age })),
);
console.log(name);
console.log(age);
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
const Address = () => {
const address = useStore((state) => state.address);
console.log(address);
return <div>Address: {address}</div>;
};
const App = () => {
const { setName, setAge, setAddress } = useStore(
useShallow((state) => ({
setName: state.setName,
setAge: state.setAge,
setAddress: state.setAddress,
})),
);
console.log("app Rendered");
return (
<div>
<UserInfo />
<Address />
<button onClick={() => setName("Jane")}>Change Name</button>
<button onClick={() => setAddress("Wall.St")}>Change Address</button>
<button onClick={() => setAge(31)}>Change Age</button>
</div>
);
};
export default App;
changeName
, changeAge
실행userInfo
컴포넌트 리렌더
changeAddress
실행Address
컴포넌트 리렌더
useShallow
를 쓰면 📌1과 동일하게 작동한다.(신기방기)
이렇게 해서 불필요한 렌더링을 줄이는구나!
내가 찾은건 여기까지 shallow
를 쓰면 구조 분해 할당으로 가져올 수 있고
해당 객체를 참조하는 방법이 얕은 복사로 달라진다.
import { create } from "zustand";
import { useShallow } from "zustand/react/shallow";
const useStore = create((set) => ({
name: "John",
age: 30,
address: "123 Main St",
setName: (name) => set({ name }),
setAge: (age) => set({ age }),
setAddress: (address) => set({ address }),
}));
const UserInfo = () => {
const { name, age } = useStore(
useShallow((state) => ({ name: state.name, age: state.age })),
);
/**
*
*/
// 기존
// const name = useStore((state) => state.name);
// const age = useStore((state) => state.age);
// 구조 분해 할당
// const { name, age } = useStore();
console.log(name);
console.log(age);
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
const Address = () => {
const address = useStore((state) => state.address);
console.log(address);
return <div>Address: {address}</div>;
};
const App = () => {
// 기존 코드
// const setName = useStore((state) => state.setName);
// const setAge = useStore((state) => state.setAge);
// const setAddress = useStore((state) => state.setAddress);
// 구조 분해 할당
// const { setName, setAge, setAddress } = useStore();
const { setName, setAge, setAddress } = useStore(
useShallow((state) => ({
setName: state.setName,
setAge: state.setAge,
setAddress: state.setAddress,
})),
);
console.log("app Rendered");
return (
<div>
<UserInfo />
<Address />
<button onClick={() => setName("Jane")}>Change Name</button>
<button onClick={() => setAddress("Wall.St")}>Change Address</button>
<button onClick={() => setAge(31)}>Change Age</button>
</div>
);
};
export default App;