ホームページ ウェブフロントエンド jsチュートリアル React 開発者向けの包括的な Redux ツールキットのメモ

React 開発者向けの包括的な Redux ツールキットのメモ

Jan 15, 2025 am 07:37 AM

Comprehensive Redux Toolkit Notes for React Developers

? Redux ツールキットのメモ ?

Redux とは何ですか?
Redux は、アプリケーションの状態を個別に管理する JS アプリ用の柔軟な状態コンテナーです。アプリケーションの状態を 1 つのストアで管理するため、アプリ全体にわたる複雑な状態ロジックの処理が容易になります。

Redux を使用する理由
通常のフローでは、コンポーネント間で状態を渡すためにプロップドリルを行う必要があります。一部のレベルではここでの状態を必要としませんが、これは負担です。また、大規模な中型アプリの状態を引き上げるには構造的な変更が必要なため、スケーラブルなソリューションではありません。だからこそ、状態を管理するために redux が必要なのです。ここでのすべての状態はストアに保持され、必要なコンポーネントはそのストアにサブスクライブするだけで済みます。 Redux は、一方向のデータ フローを強制することで、予測可能な状態管理、デバッグの容易化、スケーラビリティの向上を保証します。

コア Redux コンポーネント:

アクション: 何が起こったかを説明するオブジェクト。通常、これにはタイプとオプションのペイロードが含まれます。 (コマンド)
Dispatch: 状態を更新するためにストアにアクションを送信するために使用される関数。 (イベント発生中)
Reducer: 現在の状態とアクションを受け取り、新しい状態を返す純粋な関数。 (アクションのディスパッチ時にトリガーされる関数)

インストール: npm i @reduxjs/toolkit reverse-redux

Redux ワークフロー:

スライスの作成:
スライスは、単一の機能に対する Redux Reducer ロジックとアクションのコレクションです。 prepare コールバックを使用すると、アクション ペイロードがリデューサーに到達する前にカスタマイズできます。

import { createSlice, nanoid } from "@reduxjs/toolkit";

const postSlice = createSlice({
 name: "posts",
 initialState: [],
 reducers: {
   addPost: {
     reducer: (state, action) => {
       state.push(action.payload);
     },
     prepare: (title, content) => ({
       payload: { id: nanoid(), title, content },
     }),
   },
   deletePost: (state, action) => {
     return state.filter((post) => post.id != action.payload);
   },
 },
});

export const { addPost, deletePost } = postSlice.actions;

export default postSlice.reducer;
ログイン後にコピー
ログイン後にコピー

ストアの作成:

import { configureStore } from "@reduxjs/toolkit";
import postReducer from "../features/posts/postSlice";

export const store = configureStore({
   reducer: {
       posts: postReducer
   },
 });

ログイン後にコピー
ログイン後にコピー

プロバイダーでラップ:

import { Provider } from "react-redux";
import { store } from "./app/store.jsx";

createRoot(document.getElementById("root")).render(
 <StrictMode>
   <Provider store={store}>
     <App />
   </Provider>
 </StrictMode>
);
ログイン後にコピー
ログイン後にコピー

コンポーネントで使用:

const PostList = ({ onEdit }) => {
 const posts = useSelector((state) => state.posts);
 const dispatch = useDispatch();

 return (
   <div className="w-full grid grid-cols-1 gap-6 mt-12">
     {posts.map((post) => (
       <div key={post.id}></div>
     ))}
   </div>
 );
};
ログイン後にコピー
ログイン後にコピー

Redux ブラウザ拡張機能: Redux DevTools

const store = configureStore({
  reducer: rootReducer,
  devTools: process.env.NODE_ENV !== 'production',
});
ログイン後にコピー
ログイン後にコピー

Redux での非同期操作 (Redux サンク):

Redux では、非同期操作 (API 呼び出しなど) はミドルウェアを使用して処理されます。これは、Redux がデフォルトで同期状態更新のみをサポートしているためです。非同期操作を処理するための最も一般的なミドルウェアは、Redux Thunk、createAsyncThunk を備えた Redux Toolkit (RTK)、および Redux Saga です。

実装:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

// Fetch all posts
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

// Initial State
const initialState = {
  posts: [],
  post: null,
  loading: false,
  error: null,
};

// Slice
const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      // Fetch all posts
      .addCase(fetchPosts.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchPosts.fulfilled, (state, action) => {
        state.loading = false;
        state.posts = action.payload;
      })
      .addCase(fetchPosts.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      })

      },
});

export default postsSlice.reducer;
ログイン後にコピー
ログイン後にコピー

使用例:

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchPosts, createPost, updatePost, deletePost } from './postsSlice';

const Posts = () => {
  const dispatch = useDispatch();
  const { posts, loading, error } = useSelector((state) =>state.posts);

  useEffect(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  const handleCreate = () => {
    dispatch(createPost({ title: 'New Post', body: 'This is a new post' }));
  };

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <div>
      <h1>Posts</h1>
      <button onClick={handleCreate}>Create Post</button>
     </div>
  );
};

export default Posts;
ログイン後にコピー
ログイン後にコピー

ミドルウェア
Redux のミドルウェアはディスパッチされたアクションをインターセプトし、ロギング、クラッシュ レポート、または非同期ロジックの処理を可能にします。ミドルウェアを使用すると、ディスパッチプロセスをカスタマイズできます。

const blogPostMiddleware = (storeAPI) => (next) => (action) => {
  if (action.type === 'posts/publishPost') {
    const contentLength = action.payload.content.length;

    if (contentLength < 50) {
      console.warn('Post content is too short. Must be at least 50 characters.');
      return;
    }
    console.log('Publishing post:', action.payload.title);
  }
  return next(action);
};

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(blogPostMiddleware),
});
ログイン後にコピー
ログイン後にコピー

セレクター
セレクターは、状態の特定の部分にアクセスするのに役立ちます。

export const selectCount = (state) => state.counter.value;

エラー処理
適切な状態管理によりエラーを効果的に処理します。

import { createSlice, nanoid } from "@reduxjs/toolkit";

const postSlice = createSlice({
 name: "posts",
 initialState: [],
 reducers: {
   addPost: {
     reducer: (state, action) => {
       state.push(action.payload);
     },
     prepare: (title, content) => ({
       payload: { id: nanoid(), title, content },
     }),
   },
   deletePost: (state, action) => {
     return state.filter((post) => post.id != action.payload);
   },
 },
});

export const { addPost, deletePost } = postSlice.actions;

export default postSlice.reducer;
ログイン後にコピー
ログイン後にコピー

RTK クエリ (簡易データ取得)

RTK クエリは、データのフェッチ、キャッシュ、同期を簡素化します。 RTK クエリはリクエストを自動的にキャッシュし、不必要な再フェッチを回避してパフォーマンスを向上させます。

RTK クエリのセットアップ

import { configureStore } from "@reduxjs/toolkit";
import postReducer from "../features/posts/postSlice";

export const store = configureStore({
   reducer: {
       posts: postReducer
   },
 });

ログイン後にコピー
ログイン後にコピー

コンポーネントでの使用法

import { Provider } from "react-redux";
import { store } from "./app/store.jsx";

createRoot(document.getElementById("root")).render(
 <StrictMode>
   <Provider store={store}>
     <App />
   </Provider>
 </StrictMode>
);
ログイン後にコピー
ログイン後にコピー

Immer による不変の更新

Immer を使用すると、内部で更新を不変に保ちながら、状態を直接「変更」するロジックを作成できます。

const PostList = ({ onEdit }) => {
 const posts = useSelector((state) => state.posts);
 const dispatch = useDispatch();

 return (
   <div className="w-full grid grid-cols-1 gap-6 mt-12">
     {posts.map((post) => (
       <div key={post.id}></div>
     ))}
   </div>
 );
};
ログイン後にコピー
ログイン後にコピー

突然変異と不変

Mutate: データを直接変更します。たとえば、オブジェクトまたは配列を変更します。
不変: データを直接変更する代わりに、元のデータはそのままにして、変更を適用した新しいコピーを作成します。

Immer の仕組み
Immer は、データを変更している (つまり、データを直接変更している) ように見えるコードを作成するのに役立ちますが、内部では自動的に変更を不変に保ちます。これは、JavaScript で不変のデータ構造を扱うときによくあるバグを回避するのに役立ちます。
例: Immer なし (突然変異):

const store = configureStore({
  reducer: rootReducer,
  devTools: process.env.NODE_ENV !== 'production',
});
ログイン後にコピー
ログイン後にコピー

Immer あり (不変性):

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

// Fetch all posts
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

// Initial State
const initialState = {
  posts: [],
  post: null,
  loading: false,
  error: null,
};

// Slice
const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      // Fetch all posts
      .addCase(fetchPosts.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchPosts.fulfilled, (state, action) => {
        state.loading = false;
        state.posts = action.payload;
      })
      .addCase(fetchPosts.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      })

      },
});

export default postsSlice.reducer;
ログイン後にコピー
ログイン後にコピー

これにより、手動で状態を複製して更新する必要がなくなるため、Redux (またはその他の状態管理) の操作が容易になります。 Immer はそれを自動的に実行します。

Redux 永続化:

ページが更新されても Redux 状態を維持するには、Redux Persist を統合します。これにより、Redux の状態がローカル ストレージまたはセッション ストレージに保存され、アプリが更新されたときに再ロードされます。

インストール:
npm install redux-persist

実装:

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchPosts, createPost, updatePost, deletePost } from './postsSlice';

const Posts = () => {
  const dispatch = useDispatch();
  const { posts, loading, error } = useSelector((state) =>state.posts);

  useEffect(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  const handleCreate = () => {
    dispatch(createPost({ title: 'New Post', body: 'This is a new post' }));
  };

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <div>
      <h1>Posts</h1>
      <button onClick={handleCreate}>Create Post</button>
     </div>
  );
};

export default Posts;
ログイン後にコピー
ログイン後にコピー

パーシットゲートでラップ:

const blogPostMiddleware = (storeAPI) => (next) => (action) => {
  if (action.type === 'posts/publishPost') {
    const contentLength = action.payload.content.length;

    if (contentLength < 50) {
      console.warn('Post content is too short. Must be at least 50 characters.');
      return;
    }
    console.log('Publishing post:', action.payload.title);
  }
  return next(action);
};

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(blogPostMiddleware),
});
ログイン後にコピー
ログイン後にコピー

オプションの拡張機能

localStorage の代わりに sessionStorage を使用します:
ストレージをセッションベースに変更します (ブラウザを閉じるとクリアされます):

initialState: {
  items: [],
  status: 'idle',
  error: null,
},

.addCase(fetchData.rejected, (state, action) => {
  state.status = 'failed';
  state.error = action.error.message;
});
ログイン後にコピー

選択的永続性:
状態の特定のスライスのみを永続化します:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://jsonplaceholder.typicode.com' }),
  endpoints: (builder) => ({
    getPosts: builder.query({
      query: () => '/posts',
    }),
    getPostById: builder.query({
      query: (id) => `/posts/${id}`,
    }),
    createPost: builder.mutation({
      query: (newPost) => ({
        url: '/posts',
        method: 'POST',
        body: newPost,
      }),
    }),
    updatePost: builder.mutation({
      query: ({ id, ...updatedPost }) => ({
        url: `/posts/${id}`,
        method: 'PUT',
        body: updatedPost,
      }),
    }),
    deletePost: builder.mutation({
      query: (id) => ({
        url: `/posts/${id}`,
        method: 'DELETE',
      }),
    }),
  }),
});

export const {
  useGetPostsQuery,
  useGetPostByIdQuery,
  useCreatePostMutation,
  useUpdatePostMutation,
  useDeletePostMutation,
} = api;
export default api;
ログイン後にコピー

CRUD 機能を備えた React、redux、ant デザインを使用してシンプルなブログ プロジェクトを作成しました。ぜひチェックしてみてください。
プロジェクト リンク - Redux ブログ アプリ

? Redux Toolkit をマスターして React アプリをレベルアップしましょう!

以上がReact 開発者向けの包括的な Redux ツールキットのメモの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへ:すべてがどのように機能するか C/CからJavaScriptへ:すべてがどのように機能するか Apr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptとWeb:コア機能とユースケース JavaScriptとWeb:コア機能とユースケース Apr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScript in Action:実際の例とプロジェクト JavaScript in Action:実際の例とプロジェクト Apr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンの理解:実装の詳細 JavaScriptエンジンの理解:実装の詳細 Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

Python vs. JavaScript:開発環境とツール Python vs. JavaScript:開発環境とツール Apr 26, 2025 am 12:09 AM

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

JavaScript通訳者とコンパイラにおけるC/Cの役割 JavaScript通訳者とコンパイラにおけるC/Cの役割 Apr 20, 2025 am 12:01 AM

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

See all articles