Zustandとは? Reactフロントエンドの状態管理

zustand
Zustand

 

Zustand マスコット

序文

なぜこの技術を共有したいのですか?

Zustatnd自体はReduxに比べると比較的新しい技術で、私のチームが仕事で実装しようとしているフロントエンドの状態管理技術でもある。実際の実装を通して、いくつかの経験やアイデアを得て、この記事を書くことを思いついた。

既存の構造の問題点は?

ReduxにしろContextにしろ、状態管理を扱うにはZustandの方が複雑で、後からプロジェクトに参加したエンジニアが理解するのに時間がかかる。 Zustandの最大の目的は、フロントエンドの状態管理を比較的シンプルでわかりやすくすることであり、この特徴によってZustandが選ばれる企業もある。


コンディション管理について

ズスタンドを紹介する前に、"コンディション・マネジメント "とは何か?

現在、ウェブページはますます複雑化しており、フロントエンドとバックエンドには違いがある。フロントエンドは、画面表示、UI(UX)、ユーザーフロー、動作バージョンの有無によるデバイスの違い......などに重点を置いている。
バックエンドは、データベース管理、ログイン、登録...などを含む、より機能的な実装である。

その後、フロントエンドはますます複雑になり、フレームワークという概念も持ち始め、現在人気のある3大フレームワークは、それぞれReact、Vue、Angularである。

フレームワークが異なれば、例えば「状態管理」の方法も異なる:
React:基本的には、データを管理し、「状態」からレンダリングするだけだ。
Vue: データとコンポーネントの「双方向バインディング

Reactフレームワークに基づいて、大きく以下のカテゴリーに分けられる。

Local State

    • useState

    • useReducer

Context

    • useContext

第三者機関

    • Redux

    • Mobx

    • Zustand

ここからわかるように、Reactフレームワークにおける「状態管理」だけでも、すでにかなり複雑なものになっている。

そのため、本稿ではツスタンドのみに焦点を当て、実例も交えて紹介する。

また、Redux、Mobx、Zustandの3つのパッケージの総ダウンロード数を比較することで、この1年間でどれだけ人気があったかを見ることができる。

Zustand npm doanload

 

https://npmtrends.com/mobx-vs-react-redux-vs-zustand


Zustand それは何ですか?

Zustandによれば、これはFluxとHookのコンセプトに基づいた、軽量で高速な「状態管理」スイートだという。

p.s.上のクマは、Zustand の象徴的なマスコット!

Zustandはまた、ゾンビの子問題、Reactの同時実行、コンテキスト・ロスなど、複雑なReactの状態管理の問題を解決するために設計されている。

これらの問題について詳しく知りたい場合は、以下のリンクを参照されたい。

Zombie Child Problem:React Redux 書類

React Concurrency:React 公文書

React Context Loss:Stack Overflow

Zustandの公式サイトからも、打倒 Redux の意欲をうかがい知ることができる。


Zustand 使用状況

次の2つの簡単な使い方は、JavaScriptユーザー向けである。

最初の Store

ZustandはHooksの上に構築されるので、最初に構築されるのはCustom Hookによって作成される Storeで、変数、オブジェクト、関数などを含むことができる。そして、SetやGetを使ってデータの「状態管理」を行うことができる。

				
					import create from 'zustand' const useBearStore = create((set) => ({ bears: 0, raisePopulation: () => set((state) => ({ bears: state.bears + 1 })), RemoveAllBears: () => set({ bears: 0 }), }))
				
			
コンポーネントの結合

Hook を使うので、どのコンポーネントにも直接読み込んで使うことができる。
また、これらの状態をわずか数行で表現することも可能であり、これは Zustand における大きな恩恵である。

TypeScriptユーザーのために、Zustandの簡単な例を挙げよう。

				
					function BearCounter() { const bears = useBearStore((state) =&gt; state.bears) return <h1><span class="ez-toc-section" id="bears-around-here"></span>このあたりに{クマ}がいます...<span class="ez-toc-section-end"></span></h1>
} function Controls() { const増加Population = useBearStore((state) =&gt; state.increasePopulation) return <button onclick="{increasePopulation}">ワンアップ</button>
}

				
			

Zustand TypeScript 文体

Zustandでは、createを使って新しい store を作る。 
関数を渡し、Hook を通して状態を戻し、再びレンダリングする。

				
					import create from "zustand" type Product = { sku: 文字列; 名前: 文字列; 画像: 文字列 } type CartState = { products: Product[] カート: { [sku: 文字列]: 番号 } addToCart: (sku: string) = > void RemoveFromCart: (sku: string) => void } // セレクター // ... // 初期値と状態を変更するアクションでストアを初期化します。 export const useCart = create<CartState>(set => ( { 製品 : [ // ... ]、カート: {}、// アクション // ... }))
				
			

ここでは、ReduxとMobxがどのように書かれているかも示すので、読者は違いを比較することができるが、この記事ではReduxやMobxには焦点を当てず、Zustandとその状態管理だけに焦点を当てる。

Redux TypeScript 文体

				
					import { createSlice, configureStore, PayloadAction } from "@reduxjs/toolkit" import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux" // スライス // 状態の形状とそれを変更する方法を定義します type ICart = { [ sku: 文字列]: 数値 } const carInitialState: ICart = {} const cartSlice = createSlice({ name: "cart",InitialState:cartInitialState, Reducers: { // ... }, }) type IProduct = { sku: string;名前: 文字列; イメージ: 文字列 } const productsInitialState: IProduct[] = [ // ... ] const productsSlice = createSlice({ name: "products"、initialState: productsInitialState、reducers: {}, }) // アクション // ... // セレクター // ... // ストアのエクスポート const store = configureStore({レデューサー: { カート: cartSlice.reducer, 製品: productsSlice.reducer, }, }) // ... const App = () => { return ( <Provider store={store}> <NavigationContainer> <Stack.Navigator>{/* ... */}</Stack.Navigator> <StatusBar style="auto" /> </NavigationContainer> < /プロバイダ> ) }
				
			

Mobx TypeScript 文体

				
					import { types, Instance } from "mobx-state-tree" const Product = types.model({ sku:types.string, name:types.string, image:types.string, }) // データをモデル化して型付けします。 mobx 状態ツリー const CartStore = types .model("CartStore", { products:types.array(Product), cart:types.map(types.number), }) // 状態を変更するアクション .actions(store => ({ // ... })) // ビューはセレクターのようなものです .views(self => ({ // ... })) type CartStoreType = Instance<typeof CartStore> // ストアを使用するフックをスピンアップしますそれに初期値を指定します let _cartStore: CartStoreType export const useCart = () => { if (!_cartStore) { _cartStore = CartStore.create({ products: [ // ... ], カート: {}, } ) } _cartStore を返す }
				
			

ズスタンドはコンテクストとリダックスを超えられるか?

 

https://github.com/pmndrs/zustand#why-zustand-over-redux

ツスタンド関係者によれば、上記の点を列挙し、ここで簡単に説明している。

Redux

Redux自体はより複雑な状態管理ツールであり、アクティオイン、ビュー、ステートプロセスが存在する。

下記は公式のReduxデータフロー図だが、Reduxのステート管理ツールをゼロから使いたい場合、学習の敷居が比較的高いこともわかる。

Redux Data Flow

 

Redux Data Flow

Redux Data Flow and React Component Life Cycle
Reduxを学ぼうとするほとんどの人は、この画像を見たことがあるだろう。今の僕にとってはとても簡単なことなんだけど...。dev.to

Context

コンテキストそのものは状態管理に分類されるが、実際には状態をトリガーするための集中的な方法である。

ツスタンドと比べると、さまざまなファイルに分散しているため、管理は容易ではない。

Context Data Flow

 

Context Data Flow

[React] Context API
Reactでデータを管理するには、Props、State、Contextを使います。今回のブログでは、Contextとは何かを紹介する。dev-yakuza.posstree.com


結語

この技術を使う利点

Zustandを使えば、複雑なビジネスロジックのデータやロジックを分解してモジュール化することができます。可読性が高まるだけでなく、テストも書きやすくなります。

ヒントとコツ

Zustand自体は、状態管理ツールの学びやすさが満載で、Set、Getなどコンポーネントでの状態や使い方が比較的便利な製品で、Reactの状態管理をターゲットにしたい読者にお勧めの一冊だ。

ご視聴ありがとうございました。ご質問やご相談がありましたら、お気軽にコメントを残すか、プライベート・メッセージをお送りください!

引用

https://github.com/pmndrs/zustand

https://react-redux.js.org/api/hooks#stale-props-and-zombie-children

https://docs.pmnd.rs/zustand/getting-started/comparison

その他の参考記事

なぜ大企業はNxを使うのか? モノレポツール 5分のクイックセットアップ

モノレポを本当に知っていますか? 5分で学ぶフロントエンド・メガアーキテクチャー

ja日本語