Reduxをあなたの反応TypeScriptアプリで使う方法


ReduxはJavaScriptアプリの予測可能な状態コンテナです.それは反応アプリの状態を管理するための人気のライブラリです.JavaScriptのSuperSetは、それが堅牢で理解できるようにコードをチェックするSuperSScriptと一緒に使用するときに、より良い開発者の経験を提供することができます.
このガイドでは、私はどのように追加、削除、および記事を表示することができますアプリケーションを構築することによってあなたの反応TypeScriptプロジェクトでReduxを使用する方法を示します.
飛び込みましょう
あなたはsubscribe to my newsletter あなたの受信トレイ内の毎週の無料記事を受信します.
  • Prerequisites
  • Setting up
  • Create the types
  • Create the action types
  • Create the action creators
  • Create a reducer
  • Create a store
  • Create the components
  • 必要条件


    このチュートリアルでは、少なくともReaction、Redux、およびTypeScriptの基本的な理解を持っていると仮定します.だから、これらの技術に精通していない場合は、まず読んでくださいpractical guide to TypeScript or this React Redux tutorial - さもないと始めましょう.

    設定


    ReduxとTypesScriptを使用するには、我々は新しい反応アプリを作成する必要があります.
    そのためにはCLI (コマンドラインインタフェース)を開き、このコマンドを実行しましょう.
      npx create-react-app my-app --template typescript
    
    次に、次のようにプロジェクトを構成します.
    ├── src
    |  ├── components
    |  |  ├── AddArticle.tsx
    |  |  └── Article.tsx
    |  ├── store
    |  |  ├── actionCreators.ts
    |  |  ├── actionTypes.ts
    |  |  └── reducer.ts
    |  ├── type.d.ts
    |  ├── App.test.tsx
    |  ├── App.tsx
    |  ├── index.css
    |  ├── index.tsx
    |  ├── react-app-env.d.ts
    |  └── setupTests.ts
    ├── tsconfig.json
    ├── package.json
    └── yarn.lock
    
    プロジェクトのファイル構造は非常に簡単です.しかし、注意すべきことは二つあります.
  • The store 反応Reduxに関連するファイルを含むフォルダ.
  • The type.d.ts インポートすることなく他のファイルで使用できるタイプスクリプトタイプを保持するファイル.
  • つまり、我々は今RedUxをインストールし、我々の非常に最初の店を作成することができます.
    プロジェクトを開いて次のコマンドを実行しましょう.
      yarn add redux react-redux redux-thunk
    
    またはnpm
      npm install redux react-redux redux-thunk
    
    また、それらの型を開発依存関係としてインストールする必要があります.
    それで、CLIで再びこのコマンドを実行しましょう.
      yarn add -D @types/redux @types/react-redux @types/redux-thunk
    
    またはnpm
      npm install -D @types/redux @types/react-redux @types/redux-thunk
    
    すごい!この手順を進めると、次の節でプロジェクトの型スクリプトを作成できます.

    型を作成する


    型スクリプトの種類を使用すると、変数の種類、関数のパラメータなどを設定できます.
  • 種類D . TS
  • interface IArticle {
      id: number
      title: string
      body: string
    }
    
    type ArticleState = {
      articles: IArticle[]
    }
    
    type ArticleAction = {
      type: string
      article: IArticle
    }
    
    type DispatchType = (args: ArticleAction) => ArticleAction
    
    ここでは、インターフェイスを宣言することから始めますIArticle それは、与えられた記事の形を反映します.では、私たちはArticleState , ArticleAction , and DispatchType これは、状態オブジェクト、アクションクリエーター、およびreduxによって提供されるディスパッチ機能のそれぞれとして機能します.
    つまり、我々は現在、反応Reduxを使用して起動するために必要な型を持っている.アクションタイプを作成しましょう.

    アクションタイプを作成する

  • ストア/アクションタイプ.TS
  • export const ADD_ARTICLE = "ADD_ARTICLE"
    export const REMOVE_ARTICLE = "REMOVE_ARTICLE"
    
    reduxストアには2種類のアクションタイプが必要です.削除するための記事を追加するためのもの.

    アクションクリエーターを作成する

  • ストア/アクション.TS
  • import * as actionTypes from "./actionTypes"
    
    export function addArticle(article: IArticle) {
      const action: ArticleAction = {
        type: actionTypes.ADD_ARTICLE,
        article,
      }
    
      return simulateHttpRequest(action)
    }
    
    export function removeArticle(article: IArticle) {
      const action: ArticleAction = {
        type: actionTypes.REMOVE_ARTICLE,
        article,
      }
      return simulateHttpRequest(action)
    }
    
    export function simulateHttpRequest(action: ArticleAction) {
      return (dispatch: DispatchType) => {
        setTimeout(() => {
          dispatch(action)
        }, 500)
      }
    }
    
    このチュートリアルでは、HTTPリクエストを0.5秒間遅延させてシミュレートします.しかし、あまりにもしたい場合は、実際のサーバーを使用して自由に感じる.
    ここでは、関数addArticle 新しい記事を追加するためのアクションを送信し、メソッドremoveArticle は逆であるため、引数として渡されたオブジェクトを削除します.

    還元剤を作る


    還元器は、ストアの状態とパラメータとしてのアクションを受け取り、それから更新された状態を返す純粋な関数です.
  • ストア/減速.TS
  • import * as actionTypes from "./actionTypes"
    
    const initialState: ArticleState = {
      articles: [
        {
          id: 1,
          title: "post 1",
          body:
            "Quisque cursus, metus vitae pharetra Nam libero tempore, cum soluta nobis est eligendi",
        },
        {
          id: 2,
          title: "post 2",
          body:
            "Harum quidem rerum facilis est et expedita distinctio quas molestias excepturi sint",
        },
      ],
    }
    
    ここで見ることができるように、ページが読み込まれるときに表示するいくつかの記事を持つ初期状態を宣言します.状態オブジェクトは型に一致する必要がありますArticleState - それ以外の場合、typescriptはエラーをスローします.
  • ストア/減速.TS
  • const reducer = (
      state: ArticleState = initialState,
      action: ArticleAction
    ): ArticleState => {
      switch (action.type) {
        case actionTypes.ADD_ARTICLE:
          const newArticle: IArticle = {
            id: Math.random(), // not really unique
            title: action.article.title,
            body: action.article.body,
          }
          return {
            ...state,
            articles: state.articles.concat(newArticle),
          }
        case actionTypes.REMOVE_ARTICLE:
          const updatedArticles: IArticle[] = state.articles.filter(
            article => article.id !== action.article.id
          )
          return {
            ...state,
            articles: updatedArticles,
          }
      }
      return state
    }
    
    export default reducer
    
    次に、我々はreducer 前の状態とアクションがストアを更新できると予想する関数.ここでは、2つの動作があります.
    その点で、我々は現在還元器で州を扱うことができます.プロジェクトのためのストアを作成しましょう.

    店を作る


    Reduxストアは、あなたのアプリケーションの状態の生活です.
  • インデックス.TSX
  • import * as React from "react"
    import { render } from "react-dom"
    import { createStore, applyMiddleware, Store } from "redux"
    import { Provider } from "react-redux"
    import thunk from "redux-thunk"
    
    import App from "./App"
    import reducer from "./store/reducer"
    
    const store: Store<ArticleState, ArticleAction> & {
      dispatch: DispatchType
    } = createStore(reducer, applyMiddleware(thunk))
    
    const rootElement = document.getElementById("root")
    render(
      <Provider store={store}>
        <App />
      </Provider>,
      rootElement
    )
    
    ご覧のように、還元機能をインポートし、メソッドに引数として渡しますcreateStore ために新しいreduxストアを作成します.The redux-thunk ミドルウェアは、非同期コードを扱うことができる方法と同様に、第2のパラメータとして進められる必要があります.
    次に、私たちは、Reduxにstore への小道具としてのオブジェクトProvider コンポーネント.
    我々は今、このプロジェクトでReduxを使用して、ストアにアクセスできます.そこで、データを取得して操作するコンポーネントを作成しましょう.

    コンポーネントの作成

  • コンポーネント.TSX
  • import * as React from "react"
    
    type Props = {
      saveArticle: (article: IArticle | any) => void
    }
    
    export const AddArticle: React.FC<Props> = ({ saveArticle }) => {
      const [article, setArticle] = React.useState<IArticle | {}>()
    
      const handleArticleData = (e: React.FormEvent<HTMLInputElement>) => {
        setArticle({
          ...article,
          [e.currentTarget.id]: e.currentTarget.value,
        })
      }
    
      const addNewArticle = (e: React.FormEvent) => {
        e.preventDefault()
        saveArticle(article)
      }
    
      return (
        <form onSubmit={addNewArticle} className="Add-article">
          <input
            type="text"
            id="title"
            placeholder="Title"
            onChange={handleArticleData}
          />
          <input
            type="text"
            id="body"
            placeholder="Description"
            onChange={handleArticleData}
          />
          <button disabled={article === undefined ? true : false}>
            Add article
          </button>
        </form>
      )
    }
    
    新しい記事を追加するには、このフォームコンポーネントを使用します.関数を受け取るsaveArticle パラメータとしてストアに新しい記事を追加できます.記事オブジェクトはタイプに従わなければなりませんIArticle 活字を幸せにするために.
  • コンポーネント.TSX
  • import * as React from "react"
    import { Dispatch } from "redux"
    import { useDispatch } from "react-redux"
    
    type Props = {
      article: IArticle
      removeArticle: (article: IArticle) => void
    }
    
    export const Article: React.FC<Props> = ({ article, removeArticle }) => {
      const dispatch: Dispatch<any> = useDispatch()
    
      const deleteArticle = React.useCallback(
        (article: IArticle) => dispatch(removeArticle(article)),
        [dispatch, removeArticle]
      )
    
      return (
        <div className="Article">
          <div>
            <h1>{article.title}</h1>
            <p>{article.body}</p>
          </div>
          <button onClick={() => deleteArticle(article)}>Delete</button>
        </div>
      )
    }
    
    The Article コンポーネントは、オブジェクトオブジェクトを示します.
    機能removeArticle は、ストアにアクセスするため、与えられた記事を削除するために派遣する必要があります.それが我々がここで使用する理由ですuseDispatch 取り外しのアクションを完了するためにreduxによって提供するフック.
    次に、useCallback 依存性として値を記憶することによって不必要な再レンダリングを避けるのを助けます.
    我々は最終的にコンポーネントを追加し、記事を表示する必要があります.今では、パズルに最後のピースを追加しましょうApp.tsx ファイル.
  • アプリ.TSX
  • import * as React from "react"
    import { useSelector, shallowEqual, useDispatch } from "react-redux"
    import "./styles.css"
    
    import { Article } from "./components/Article"
    import { AddArticle } from "./components/AddArticle"
    import { addArticle, removeArticle } from "./store/actionCreators"
    import { Dispatch } from "redux"
    
    const App: React.FC = () => {
      const articles: readonly IArticle[] = useSelector(
        (state: ArticleState) => state.articles,
        shallowEqual
      )
    
      const dispatch: Dispatch<any> = useDispatch()
    
      const saveArticle = React.useCallback(
        (article: IArticle) => dispatch(addArticle(article)),
        [dispatch]
      )
    
      return (
        <main>
          <h1>My Articles</h1>
          <AddArticle saveArticle={saveArticle} />
          {articles.map((article: IArticle) => (
            <Article
              key={article.id}
              article={article}
              removeArticle={removeArticle}
            />
          ))}
        </main>
      )
    }
    
    export default App
    
    The useSelector フックは、ストアの状態へのアクセスを可能にします.こちらではパスshallowEqual 変更をチェックする際に浅い値を使用するためにreduxに指示するメソッドの2番目の引数として.
    次に、我々は依存してuseDispatch 店に物品を入れる行為をすること.最後に、我々は記事の配列をループし、それぞれに渡すArticle コンポーネントを表示します.
    これにより、プロジェクトのルートを参照し、このコマンドを実行できます.
      yarn start
    
    またはnpm
      npm start
    
    あなたが開くならばhttp://localhost:3000/ ブラウザでは次のようになります.

    すごい!我々のアプリは良い見えます.これにより、我々は今反応のtypescriptアプリでreduxを使用して終了しました.
    完成したプロジェクトを見つけることができますin this CodeSandbox
    このような他の偉大なコンテンツを見つけることができますmy blog または通知を得るために私に従ってください.
    読書ありがとう.