Rapid Prototyping Made Easy with React PowerPlug

joshtronic

If you’re trying to rapid prototype an app the last thing you want to be doing is implementing the same state management logic over and over. Adding something like Redux can help but tends to just adds a layer of complexity that can slow you down every further. React PowerPlug makes rapid prototyping a breeze by introducing a set of stateful components that let you focus on the good stuff, actually prototyping!

React PowerPlug is a set of renderless components that provide different types of state management scenarios by way of render props. The project is dependency-free, well documented and pretty small at around 3kb.

A word of warning though, the project’s master branch is still considered unstable and under active development. I opted to talk about the unstable version because it has so much more to offer in terms of different types of stateful components.

Getting Started

To get things started, we will need to add React PowerPlug to our project:

Via npm

$ npm install --save react-powerplug

Or via Yarn

$ yarn add react-powerplug

With the dependency added to our project, we will need to import React PowerPlug in it’s entirety:

import ReactPowerPlug from "react-powerplug";

Or import the individual components we’d like to use:

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

Examples

As mentioned, the master branch of this project has a ton of additional stateful components.

While the type of data may be different between the components, nearly all of the components accept an initial property to set the default state.

Managing State

A component’s state can come in many different forms. It could be as simple as holding a single value or as complex as a mixed bag of boolean values, counters and string values.

State

State is one of the more basic components. Very similar to React’s baked in state property, State allows you to maintain an object of state properties that can updated via 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 is a component for maintaining the state of a boolean value:

<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 allows you to increment and decrement an integer in the state:

<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 is for maintaining the state of a single value. Set it and forget it:

<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

The Map component is quite similar to State as it controls state as an object with different properties. Where it differs is that you interact with the state via get and set methods:

<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

Not to be confused with the aforementioned set method, the Set component manages it’s state as an array of values which you can add to and remove from:

<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

List also holds it’s state as an array. Instead of simple add and remove methods, you interact with the array via push and pull methods.

Considering the complexity that is introduced by needing to know the index of the array item when pulling from the state, I’d probably just stick to 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>

Managing User Interactions

Keeping track of a user’s interaction with a component usually includes binding event handlers on top of keeping track of the current state. React PowerPlug does a great job of not only combining these implementations but also keeping you fairly insulated from needing to worry about event handlers.

Hover

Hover keeps track of whether or not a user is hovering over a component:

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

Active

Active knows if a user is clicking on a component:

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

Touch

Similar to Active, the Touch component is the touch-friendly equivalent:

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

Focus

Focus is perfect for showing and hiding information based on which field a user is currently interacting with:

<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>

Forms

Even though React PowerPlug has components that could easily be used to wrap up form components, they still took the time to include some form-specific components to help save you time:

Input

Input, which works with input instead of replacing it, binds input events to an input or any form field and stashes the value in the state:

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

Form

The Form component takes things a step further by allowing you to track the state of multiple fields on a form with ease:

<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>

Timers

React PowerPlug isn’t just for tracking state variables and user input, you can also use it wire up components to update automatically.

Interval

Unlike the other components we’ve discussed, Interval doesn’t take an initial state value and instead takes delay (in milliseconds).

<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>

Conclusion

React PowerPlug stands up to the claims that it makes it easy to rapid prototype apps in React. As the project is very much a work in progress right now, I’m super excited to see where the team ends up taking it!

I hope that you enjoyed this run down of React PowerPlug and if you are interested in seeing the code samples in action, you can head over to CodeSandbox.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#