📊
React ContextとJotaiとValtioとZustandでカウンターアプリのサイズ比較
React Contextを使ったコード
import { createContext, useContext, useState } from "react";
const createCountContext = (initialValue) => {
const CountContext = createContext(initialValue);
const CountProvider = ({ children }) => (
<CountContext.Provider value={useState(initialValue)}>
{children}
</CountContext.Provider>
);
const useCount = () => useContext(CountContext);
return { CountProvider, useCount };
};
const {
CountProvider: CountProviderA,
useCount: useCountA
} = createCountContext(1);
const {
CountProvider: CountProviderB,
useCount: useCountB
} = createCountContext(2);
const {
CountProvider: CountProviderC,
useCount: useCountC
} = createCountContext(3);
const CounterA = () => {
const [count, setCount] = useCountA();
return (
<div>
A: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const CounterB = () => {
const [count, setCount] = useCountB();
return (
<div>
B: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const CounterC = () => {
const [count, setCount] = useCountC();
return (
<div>
C: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const App = () => (
<CountProviderA>
<CountProviderB>
<CountProviderC>
<CounterA />
<CounterA />
<CounterB />
<CounterB />
<CounterC />
<CounterC />
</CountProviderC>
</CountProviderB>
</CountProviderA>
);
export default App;
Jotaiを使ったコード
import { atom, useAtom } from "jotai";
const countAtomA = atom(1);
const countAtomB = atom(2);
const countAtomC = atom(3);
const CounterA = () => {
const [count, setCount] = useAtom(countAtomA);
return (
<div>
A: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const CounterB = () => {
const [count, setCount] = useAtom(countAtomB);
return (
<div>
B: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const CounterC = () => {
const [count, setCount] = useAtom(countAtomC);
return (
<div>
C: {count} <button onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
};
const App = () => (
<>
<CounterA />
<CounterA />
<CounterB />
<CounterB />
<CounterC />
<CounterC />
</>
);
export default App;
Valtioを使ったコード
import { proxy, useSnapshot } from "valtio";
const stateA = proxy({ count: 1 });
const stateB = proxy({ count: 2 });
const stateC = proxy({ count: 3 });
const CounterA = () => {
const { count } = useSnapshot(stateA);
return (
<div>
A: {count} <button onClick={() => ++stateA.count}>+1</button>
</div>
);
};
const CounterB = () => {
const { count } = useSnapshot(stateB);
return (
<div>
B: {count} <button onClick={() => ++stateB.count}>+1</button>
</div>
);
};
const CounterC = () => {
const { count } = useSnapshot(stateC);
return (
<div>
C: {count} <button onClick={() => ++stateC.count}>+1</button>
</div>
);
};
const App = () => (
<>
<CounterA />
<CounterA />
<CounterB />
<CounterB />
<CounterC />
<CounterC />
</>
);
export default App;
Zustandを使ったコード
import create from "zustand";
const createCountStore = (initialValue) =>
create((set) => ({
count: initialValue,
inc: () => set((prev) => ({ count: prev.count + 1 }))
}));
const useStoreA = createCountStore(1);
const useStoreB = createCountStore(2);
const useStoreC = createCountStore(3);
const CounterA = () => {
const count = useStoreA((state) => state.count);
const inc = useStoreA((state) => state.inc);
return (
<div>
A: {count} <button onClick={inc}>+1</button>
</div>
);
};
const CounterB = () => {
const count = useStoreB((state) => state.count);
const inc = useStoreB((state) => state.inc);
return (
<div>
B: {count} <button onClick={inc}>+1</button>
</div>
);
};
const CounterC = () => {
const count = useStoreC((state) => state.count);
const inc = useStoreC((state) => state.inc);
return (
<div>
C: {count} <button onClick={inc}>+1</button>
</div>
);
};
const App = () => (
<>
<CounterA />
<CounterA />
<CounterB />
<CounterB />
<CounterC />
<CounterC />
</>
);
export default App;
ビルドした結果
$ (cd context-counters; yarn build)
File sizes after gzip:
41.71 KB build/static/js/2.096dca2e.chunk.js
784 B build/static/js/runtime-main.1b7e5d07.js
550 B build/static/js/main.f99437d3.chunk.js
$ (cd jotai-counters; yarn build)
File sizes after gzip:
44.75 KB build/static/js/2.6faf9917.chunk.js
779 B build/static/js/runtime-main.8b9abacf.js
442 B build/static/js/main.0aff4939.chunk.js
$ (cd valtio-counters; yarn build)
File sizes after gzip:
44.55 KB build/static/js/2.01ebfb38.chunk.js
782 B build/static/js/runtime-main.436c500d.js
447 B build/static/js/main.94b85785.chunk.js
$ (cd zustand-counters; yarn build)
File sizes after gzip:
44.48 KB build/static/js/2.1770fde7.chunk.js
783 B build/static/js/runtime-main.1e7f31f0.js
462 B build/static/js/main.879b382e.chunk.js
Discussion