ビルドMobxとあなたの最初のアプリと反応


MobX もう一つの州管理ライブラリは、他に反応アプリのために利用できますRedux and Context API . しかし、Mobxだけではなく、反応のためのライブラリではない、それはまた、他のJavaScriptライブラリとWebアプリケーションのフロントエンドを電源フレームワークとの使用に適しています.Mobx >= 5のバージョンはES 6プロキシをサポートする任意のブラウザで動作します.

主な概念


ここではMobxの主要な概念です
観測できる
オブザーバブルは、他のものがこれらの観測可能な変更と値を追跡できるように、任意のデータ構造またはプロパティを観測可能な状態にすることができます.
アクション
このアクションは、状態を監視することができます.状態データはコードスケーラビリティを確保するために外側のアクションを変更すべきではありません.
計算
計算されたプロパティを使用すると、状態変化に基づいていくつかの値を取得できます.計算された値はオブザーバブル上で何らかの計算を行うことによって得られる.
観測者
オブザーバは、反応がどんな変化でも通知されて、再描画を開始するように、オブザーバブルの変化を追跡するのを許します.彼らはMobX反応パッケージによって提供されます.

その店はデータ源だ.Remoxとは異なり、MOVXデータとデータは、ストア内のライブを変更する関数で.それで、店はオブザーバブルと行動を含むかもしれません.

Very in a nutshell mobx works on the observable — observer flow. You declare some data to be observable and when that data changes all the observers that are using that data will be notified.


では、これらの概念を実行しましょう.
我々は、ユーザーが画像に反応することができるシンプルなアプリケーションを作成し、それにコメントをFacebookに似ています.ここではlink to the demo .

プロジェクト設定
反応の事前知識を仮定すると、必要がありますNPM and Node.js あなたのマシンにインストールされます.
私は、カスタムWebパックの設定を使用して、デコレーターを有効にするプロジェクトを設定します.心配しないでください、また、装飾者なしでこれをする別の方法があります.この例では、より簡潔なので、デコレータを使用しています.しかし、私は同様に選択肢に言及します.あなたはこれらのセットアップ手順をスキップすることができます作成反応アプリを使用している場合.
プルmaster ブランチthis repository 初期設定用.
ランyarn 依存関係をインストールし、プロジェクトを起動するにはyarn start . アプリが実行されますhttp://localhost:8080.

デコレータの設定
次のプラグインは、ESNEEDデコレータを有効にするために必要です.
yarn add --dev @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators
次に、次の設定を追加します.Babelrcファイル.
"plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ],
        [
            "@babel/plugin-proposal-class-properties",
            {
                "loose": true
            }
        ]
    ]
スタイル
スタイルのためにデザイン分岐を引いてください.すべてのスタイリングはcss フォルダ内のsrc ディレクトリ.ここに我々のアプリのコンポーネントのビジュアルです.

  • カードコンポーネント
  • ランダムに生成画像.
  • カウントのコンポーネントのようなコメントやコメントの数を追跡する.
  • ボタンのコンポーネントのように、コメントボタン.
  • コメントを投稿するには、入力フィールドを使用してコンポーネントをフォームにします.
  • コメントのコメントとコンポーネントのコメント.

  • 依存関係のインストール
    インストールmobx ステートマネージメントソリューションmobx-react 状態層を反応ビュー層に接続するライブラリ.
    yarn add mobx mobx-react
    
    今、我々は実際にMobxを使用して機能を追加を開始します

    まず、私たちはAを作成するつもりですStore.jsxstore フォルダ.
    import { observable, action } from 'mobx'
    
    class Store {
        @observable likesCount = 12
    
        @action updateCount{
            this.likesCount++;
        }
    }
    
    const storeInstance = new Store()
    export default storeInstance;
    
    ここでは、私たちはlikesCount 観測可能な状態としてupdateCount 状態を変更し、その後、ストアの新しいインスタンスをエクスポートするアクションとして.
    設定がデコレータをサポートしていない場合、上記のコードを次のように書き換えることができます.
    import { decorate, observable } from "mobx";
    
    class Store {
        likesCount = 12;
    
        updateCount{
            this.likesCount++;
        }
    }
    
    decorate(Store, {
        likesCount: observable,
        updateCount: action
    })
    
    その後、我々は、アプリケーション内でコンテキストAPIを使用してそれを渡すことによって、アクセス可能な店を作るmain.js .
    
    import storeInstance from './store/Store'
    
    export const StoreContext = React.createContext();
    
    ReactDOM.render(
            <StoreContext.Provider value={storeInstance}>
                <Post />
            </StoreContext.Provider >
        , document.getElementById('app'));
    
    現在、我々は店とそのクラス特性にアクセスすることができますCount.jsx 使用useContext . 初期値を設定しましたlikesCount 12には、あなたのアプリケーションは、その値をレンダリングします.
    import React, { useContext } from 'react';
    import { StoreContext } from '../main'
    
    export default function Count() {
        const store = useContext(StoreContext)
        return (
            <div className="row reactions-count" >
                <div className="col-sm" align="left">
                    <i className="fa fa-thumbs-up" />{store.likesCount}
                </div>
                <div className="col-sm" align="right">
                    3 comments
            </div>
            </div>
        )
    }
    
    観測可能な状態はアクションを通してのみ変更できることを覚えておいてください.増加するためにlikesCount ユーザーがボタンのようにクリックするとき、我々は使用していますupdateCount 我々がすでに定義した店からの行動.ハンドルonClick アクションButtons.jsx .
    const store = useContext(StoreContext)
    <button type="button" className="btn btn-light align-top" onClick={() => store.updateCount()}>
      <i className="fa fa-thumbs-o-up" />
      Like
    </button>
    
    ボタンのような場合は、変更を表示されません.
    機能コンポーネントの変更について観察し、反応するには、コンポーネントをObserver関数でラップするか、または以下のようにUseObserverフックを実装できます.更新しましょうCount.jsx AS :
    import { useObserver } from 'mobx-react';
    
    ...
      return useObserver(() => (
            <div className="row reactions-count" >
                <div className="col-sm" align="left">
                    <i className="fa fa-thumbs-up" />{store.likesCount}
                ...
                ...
            </div>
            </div>
        ))
    
    これで、ボタンをクリックすると、カウントが更新されます.
    コメント
    コメント欄で作業を始めましょう.
    配列データ構造も同様に観測することができます.観察できるようにしましょうcomments フィールド.以下を加えるStore.jsx .
    @observable comments = ["Wow", "awesome"]
    
    次に、store classのcommentプロパティにアクセスしますComments.jsx 我々が以前にしたようにCount.jsx 使用useContext . コメントコンポーネントは、ストアからコメントをレンダリングします.
    import React, { useContext } from 'react';
    import { StoreContext } from '../main';
    
    export default function Comments() {
        const store = useContext(StoreContext)
        return (
            <table className="table">
                <tbody>
                    {
                        store.comments.map((comment, index) => {
                            return (
                                <tr key={index}>
                                    <td>
                                        {comment}
                                    </td>
                                </tr>
                            )
    
                        })
                    }
                </tbody>
            </table>
        )
    }
    
    また、フォームからコメントを追加できるようにする必要があります.
    まず、アクションを作成しましょうpostComment 単にコメントの前の配列に新しいコメントを押すストアで.次のコード行を追加しますStore.jsx .
    @action postComment(comment){
                this.comments.push(comment)
    }
    
    次に、Form.jsx コンポーネントとして
    import React, { useContext } from 'react';
    import { StoreContext } from '../main';
    
    export default class Form extends React.Component {
    
        handleSubmit = (e, store) => {
            e.preventDefault();
            store.postComment(this.comment.value);
            this.comment.value = "";
        }
    
        render() {
            return (
                <StoreContext.Consumer>
                    {
                        store => (
    
                            <form onSubmit={(e) => this.handleSubmit(e, store)}>
                                <div>
                                    <input type="text" id={'comment'} className="form-control" placeholder={"Write a comment ..."} ref={node => {
                                        this.comment = node;
                                    }} />
                                </div>
                            </form>
                        )
                    }
                </StoreContext.Consumer>
            )
        }
    }
    
    ここでは、単に店のpostComment ユーザーがコメントを送信し、入力フィールドを送信した後に空にするアクション.
    コメントを新しいコメントが追加されたときにコメントコンポーネントを更新するには、コメントコンポーネントをObserverとしてカウントする必要があります.それでComments.jsx 返される内容をラップするuseObserver . また、インポートを忘れないでくださいuseObserver .
    return useObserver(() => (
            <table className="table">
                <tbody>
                    {
                        store.comments.map((comment, index) => {
                           ...
                           ...
                    }
                </tbody>
            </table>
        )
        )
    
    今すぐコメントを書くと、コメントを自動的に更新されますリストを入力ヒット.
    コメントボタンをクリックすると入力フィールドにフォーカスしましょう.HTML DOM FORCE ()メソッドを使用することができます.まず最初に、入力フィールドをidとしましょう.
    <input type="text" id={'comment'} className="form-control" placeholder={"Write a comment ..."} 
    ref={node => {this.comment = node;}} />
    
    次にフォーカスメソッドをonClick コメントボタンのハンドラButtons.jsx コンポーネント.
    <button type="button" className="btn btn-light" 
    onClick={() => document.getElementById('comment').focus()}>
      <i className="fa fa-comment-o" />
      Comment
    </button>
    
    コメントボタンをクリックすると、コメント欄がフォーカスされます.
    計算
    今、コメントの数を得るために、我々はAを作成するつもりですcommentsCount オブザーバブルを計算するゲッター関数comments 配列の長さ.Mobxは確実になるcommentsCount 自動的にいつでも更新comments 配列の変更.インStore.jsx 次を追加します.
    @computed get commentsCount(){
                return this.comments.length;
    }
    
    次に、単に次の行を更新しますCount.jsx .
    <div className="col-sm" align="right">
          {store.commentsCount} comments
    </div>
    
    また、コメントを追加すると、カウントも同様に更新されることに注意してください.
    サービス/API呼び出し
    API呼び出しと非同期コードを作ることは、アプリケーションで頻繁です.これは、カスタムのWebpackの設定を有効にするには.babelrc 以下のファイルを指定します.
    "presets": [
            ["@babel/preset-env",
            {
                "targets": {
                  "node": "10"
                }
              }
            ],
            "@babel/preset-react"
        ],
    
    または、このエラーに遭遇するかもしれない

    イメージを変えましょうCard.jsx コンポーネントのボタンをクリックします.私たちは使用するつもりですthis 楽しさと無料のAPIは、リックとモティショーから文字のイメージを取得します.詳細はドキュメントをチェックしてください.
    あなたはから見つけるthis を追加することで、単一の文字を得ることができるセクションid パラメータとして:/character/1
    https://rickandmortyapi.com/api/character/1
    
    観察可能なイメージストアを作ろうimageUrl デフォルト値を含む.それから、我々はfetchImage 単一の文字のJSONレスポンスを返すアクション.
    アフターawait 新しい非同期関数が起動されるので、各await , 状態変更コードをアクションとしてラップする必要があります.これを行うには複数の方法があります.読めるthis section 詳細についてはMobxドキュメントを参照してください.
    つの方法はrunInAction , これは、コードブロックを取り、匿名のアクションで実行する単純なユーティリティです.ここでは、状態修正部分をrunInAction .
    import { action, runInAction, observable } from "mobx";
    
    class ImageStore {
    
        id = 1
    
        @observable imageUrl = `https://rickandmortyapi.com/api/character/avatar/1.jpeg`
    
        @action async fetchImage() {
                const characterId = ++this.id
                const response = await fetch(`https://rickandmortyapi.com/api/character/${characterId}`)
                const data = await response.json()
                runInAction(() => {
                    this.imageUrl = data.image
                })
        }
    }
    
    const imageStore = new ImageStore()
    
    export default imageStore;
    
    また、コールバックの状態変更部分だけを実行することもできます.ここでは、外部のURLを設定するアクションを作成しましたfetchImage を呼び出し、必要に応じて呼び出されます.
    class ImageStore {
    
        ... 
    
        @action async fetchImage() {
                ...
                this.setImageUrl(data.image)
        }
    
    
        @action setImageUrl(url) {
            this.imageUrl = url
        }
    }
    
    Card.jsx コンポーネント
  • インポートimageStore を設定し、画像のソースをオブザーバブルに設定するimageUrl 店から.
  • 実装useObserver 変更に反応する.
  • ボタンを加えるonClick を呼び出すハンドラfetchImage イメージURLを取得するには
  • import React from "react";
    import Count from "./Count";
    import Buttons from "./Buttons";
    import imageStore from '../store/ImageStore'
    import { useObserver } from "mobx-react";
    
    export default function Card() {
        return (
            useObserver(() => (
                <div className="card">
                    <img src={imageStore.imageUrl} className="card-img-top" alt="..." />
                    <button className="btn btn-light" onClick={() => { imageStore.fetchImage() }}>
                        <i className="fa fa-chevron-right" />
                    </button>
                    <Count />
                    <div className="card-body" >
                        <Buttons />
                    </div>
                </div>
            ))
        );
    }
    
    Aaand我々は完了です!ここにあなたのfinal output のようになります.

    注意
    店で行動を束ねることについての良いことは、我々が彼らを利用することができるということですonClick ハンドラ.これは、この例のように、コンポーネントの大部分がステートレス機能コンポーネントであることを意味します.クラスコンポーネントをオブザーバにするには@observer コンポーネントをデコレータまたはラップするobserver 関数.
        import React from "react";
        import { observer } from "mobx-react";
    
        //With decorator
        @observer
        export default class Form extends React.Component{
         ...
        }
    
        //Without decorator
    
        class Form extends React.Component{
         ...
        }
        export default observer(Form)
    
    
    Mobx docs よく書かれており、多くのベストプラクティスが含まれています.
    この例のすべてのコードを見つけることができますhere
    そしてそれです.読書ありがとう!😃