アプリのラピッドプロトタイピングを試みている場合、最後にやりたいことは、同じ状態管理ロジックを何度も実装することです。 Redux のようなものを追加することは役に立ちますが、複雑さの層を追加するだけで、さらに遅くなる可能性があります。 React PowerPlug は、優れたもの、実際にはプロトタイピングに集中できる一連のステートフルコンポーネントを導入することで、ラピッドプロトタイピングを簡単にします。

React PowerPlugは、レンダリングプロップを介してさまざまなタイプの状態管理シナリオを提供するレンダリングレスコンポーネントのセットです。 プロジェクトは依存関係がなく、十分に文書化されており、約3kbとかなり小さいです。

ただし、警告の言葉として、プロジェクトのmasterブランチはまだ不安定であり、活発に開発されていると考えられています。 さまざまなタイプのステートフルコンポーネントに関して提供できるものが非常に多いため、不安定なバージョンについて説明することにしました。

入門

開始するには、プロジェクトにReactPowerPlugを追加する必要があります。

npm経由

$ npm install --save react-powerplug

または糸経由

$ yarn add react-powerplug

プロジェクトに依存関係を追加したら、ReactPowerPlug全体をインポートする必要があります。

import ReactPowerPlug from "react-powerplug";

または、使用する個々のコンポーネントをインポートします。

import { Counter, Hover, Togggle } from "react-powerplug";

前述のように、このプロジェクトのmasterブランチには、多数の追加のステートフルコンポーネントがあります。

データのタイプはコンポーネント間で異なる場合がありますが、ほぼすべてのコンポーネントがinitialプロパティを受け入れてデフォルトの状態を設定します。

状態の管理

コンポーネントの状態は、さまざまな形で発生する可能性があります。 単一の値を保持するのと同じくらい単純な場合もあれば、ブール値、カウンター、および文字列値の混合バッグのように複雑な場合もあります。

Stateは、より基本的なコンポーネントの1つです。 stateプロパティでベイクされたReactと非常によく似ており、Stateを使用すると、setStateを介して更新できる状態プロパティのオブジェクトを維持できます。

<State initial={{ favorite: "", picked: "" }}>
  {({ state, setState }) => (
    <div>
      <button
        onClick={() =>
          setState({
            favorite: "Alligator",
            picked: new Date().toLocaleTimeString()
          })
        }
      >
        Alligator
      </button>
      <button
        onClick={() =>
          setState({
            favorite: "Crocodile",
            picked: new Date().toLocaleTimeString()
          })
        }
      >
        Crocodile
      </button>
      <button onClick={() => setState({ favorite: "", picked: "" })}>
        Reset
      </button>
      {state.favorite && state.picked && (
        <div>
          <br />You picked {state.favorite} at {state.picked}
        </div>
      )}
    </div>
  )}
</State>

トグル

Toggleは、ブール値の状態を維持するためのコンポーネントです。

<Toggle initial={false}>
  {({ on, toggle }) => (
    <div>
      <input type="checkbox" checked={on} onChange={toggle} />
      <br /><br />
      {on && <div>This box is CHECKED!</div>}
      {!on && <div>This box is NOT CHECKED!</div>}
    </div>
  )}
</Toggle>

カウンター

Counterを使用すると、次の状態の整数をインクリメントおよびデクリメントできます。

<Counter initial={0}>
  {({ count, inc, dec }) => (
    <div>
      {count === 0 && <div>There are no little alligators</div>}
      {count === 1 && <div>There is 1 little lonely alligator</div>}
      {count > 1 && <div>There are {count} little alligators</div>}
      <div>
        <br />
        <button onClick={dec}>-</button>
        <button onClick={inc}>+</button>
      </div>
    </div>
  )}
</Counter>

価値

Valueは、単一の値の状態を維持するためのものです。 それを設定し、それを忘れてください:

<Value initial="#008F68">
  {({ value, set }) => (
    <div>
      <div
        style={{
          height: 100,
          width: 100,
          background: value,
          margin: "0 auto"
        }}
      />
      <div>
        <br />
        <button onClick={() => set("#008F68")}>#008F68</button>
        <button onClick={() => set("#6DB65B")}>#6DB65B</button>
        <button onClick={() => set("#4AAE9B")}>#4AAE9B</button>
      </div>
    </div>
  )}
</Value>

地図

Mapコンポーネントは、さまざまなプロパティを持つオブジェクトとして状態を制御するため、Stateと非常によく似ています。 異なる点は、getおよびsetメソッドを介して状態と対話することです。

<Map initial={{ reptile: "", picked: "" }}>
  {({ set, get }) => (
    <div>
      <button
        onClick={() => {
          set("favorite", "Alligator");
          set("picked", new Date().toLocaleTimeString());
        }}
      >
        Alligator
      </button>
      <button
        onClick={() => {
          set("favorite", "Crocodile");
          set("picked", new Date().toLocaleTimeString());
        }}
      >
        Crocodile
      </button>
      <button
        onClick={() => {
          set("favorite", "");
          set("picked", "");
        }}
      >
        Reset
      </button>
      {get("favorite") &&
        get("picked") && (
          <div>
            <br />You picked {get("favorite")} at {get("picked")}
          </div>
        )}
    </div>
  )}
</Map>

セットする

前述のsetメソッドと混同しないように、Setコンポーネントは、その状態を、addからremoveへの値の配列として管理します。

<Set initial={["Alligator", "Crocodile"]}>
  {({ values, add, remove }) => (
    <div>
      {values.length === 0 && <div>Our set is empty!</div>}
      {values.length > 0 && (
        <div>
          {values.map(value => (
            <div>
              {value}&nbsp;
              <button onClick={() => remove(value)}>X</button>
              <br /><br />
            </div>
          ))}
        </div>
      )}
      <input
        type="text"
        placeholder="Type here and hit enter"
        onKeyPress={event => {
          if (event.key === "Enter") {
            add(event.target.value);
            event.target.value = "";
          }
        }}
      />
    </div>
  )}
</Set>

リスト

Listも、その状態を配列として保持します。 単純なaddおよびremoveメソッドの代わりに、pushおよびpullメソッドを介してアレイと対話します。

状態からpullするときに配列アイテムのインデックスを知る必要があることによってもたらされる複雑さを考えると、おそらくSetに固執するでしょう。

<List initial={["Alligator", "Crocodile"]}>
  {({ list, push, pull }) => (
    <div>
      {list.length === 0 && <div>Our list is empty!</div>}
      {list.length > 0 && (
        <div>
          {list.map(item => (
            <div>
              {item}&nbsp;
              <button onClick={() => pull(i => item === i)}>X</button>
              <br /><br />
            </div>
          ))}
        </div>
      )}
      <input
        type="text"
        placeholder="Type here and hit enter"
        onKeyPress={event => {
          if (event.key === "Enter") {
            push(event.target.value);
            event.target.value = "";
          }
        }}
      />
    </div>
  )}
</List>

ユーザーインタラクションの管理

コンポーネントとのユーザーの相互作用を追跡することには、通常、現在の状態を追跡することに加えて、イベントハンドラーをバインドすることが含まれます。 React PowerPlugは、これらの実装を組み合わせるだけでなく、イベントハンドラーについて心配する必要からかなり隔離された状態に保つという素晴らしい仕事をします。

ホバー

Hoverは、ユーザーがコンポーネントにカーソルを合わせているかどうかを追跡します。

<Hover>
  {({ hovered, bind }) => (
    <div {...bind}>
      {!hovered && <div>See you later, alligator!</div>}
      {hovered && <div>After 'while, crocodile!</div>}
    </div>
  )}
</Hover>

アクティブ

Activeは、ユーザーがコンポーネントをクリックしているかどうかを認識しています。

<Active>
  {({ active, bind }) => (
    <div {...bind}>
      {!active && <span>Click here to activate!</span>}
      {active && <span>STOP CLICKING ME!!</span>}
    </div>
  )}
</Active>

触る

Activeと同様に、Touchコンポーネントはタッチフレンドリーな同等のコンポーネントです。

<Touch>
  {({ touched, bind }) => (
    <div {...bind}>
      {!touched && <span>Touch here to trigger!</span>}
      {touched && <span>STOP TOUCHING ME!!</span>}
    </div>
  )}
</Touch>

集中

Focusは、ユーザーが現在操作しているフィールドに基づいて情報を表示および非表示にするのに最適です。

<Focus>
  {({ focused, bind }) => (
    <div>
      <input
        type="text"
        placeholder="Click to focus this input!"
        {...bind}
      />
      <div>
        {focused
          ? "Great for showing help text ONLY when focused!"
          : ""}
      </div>
    </div>
  )}
</Focus>

フォーム

React PowerPlugには、フォームコンポーネントをまとめるために簡単に使用できるコンポーネントがありますが、時間を節約するために、フォーム固有のコンポーネントを含めるのに時間がかかりました。

入力

Inputは、inputを置き換える代わりに動作し、入力イベントをinputまたは任意のフォームフィールドにバインドし、次の状態の値を隠します。

<Input initial="">
  {({ bind, value }) => (
    <div>
      <input type="text" {...bind} />
      <div>
        {value.length
          ? `You typed: ${value}`
          : "You have not typed anything :("}
      </div>
    </div>
  )}
</Input>

Formコンポーネントは、フォーム上の複数のフィールドの状態を簡単に追跡できるようにすることで、さらに一歩進んでいます。

<Form initial={{ firstName: "", lastName: "" }}>
  {({ input, values }) => (
    <form
      onSubmit={e => {
        e.preventDefault();
        console.log("Form Submission Data:", values);
      }}
    >
      <input
        type="text"
        placeholder="Your First Name"
        {...input("firstName").bind}
      />
      <input
        type="text"
        placeholder="Your Last Name"
        {...input("lastName").bind}
      />
      <input type="submit" value="All Done!" />
    </form>
  )}
</Form>

タイマー

React PowerPlugは、状態変数とユーザー入力を追跡するためだけのものではありません。コンポーネントを接続して自動的に更新することもできます。

間隔

これまでに説明した他のコンポーネントとは異なり、Intervalinitial状態値を取りませんが、代わりにdelay(ミリ秒単位)を取ります。

<Interval delay={1000}>
  {({ start, stop, toggle }) => (
    <div>
      Updates every second, last updated at:{" "}
      {new Date().toLocaleTimeString()}
      <br /><br />
      <div>
        <button onClick={() => stop()}>Stop</button>
        <button onClick={() => start()}>Start</button>
        {" or "}
        <button onClick={() => toggle()}>Toggle!</button>
      </div>
    </div>
  )}
</Interval>

結論

React PowerPlugは、Reactでアプリのラピッドプロトタイピングを簡単に行えるという主張に応えます。 プロジェクトは現在非常に進行中の作業であるため、チームが最終的にどこでプロジェクトを実施するのかを見てとても興奮しています。

このReactPowerPlugの実行を楽しんでいただければ幸いです。コードサンプルの動作を確認したい場合は、CodeSandboxにアクセスしてください。