Component-based state management for React

When I ask people what their favorite part of React is, one of the most frequent answers is “Components”.

And I agree. React’s component system is magnificent. It lets you split your code into small, single-purpose parts. It lets you work on one part of the app, while your colleagues focus on something else. It makes it simple to share useful parts with your team, and with a huge number of frontend developers all over the world.

But while React’s component system is great for creating view components, it can’t solve everything. And in particular, it can’t solve state.

Three types of state

React components are great at handling view state, like animations and transitions. And that’s no accident. After all, each React Component is tied at some level to the DOM, which is an abstraction for your application’s view.

But not all state is view state.

This is part of why Redux is so popular. It recognises that not all state is view state. It gives you somewhere to put what I call environment state, or information that must be accessible throughout your entire appliaction.

Examples of environment state include:

  • cached data
  • in-progress http requests
  • authentication

But even then, some state just doesn’t fit a Redux store.

This is because there is a third type of state, that isn’t global, and isn’t tied to the DOM. I call it control state.

As an example, consider a sign-up form component. You may want to re-use this component in multiple places. However, you may also want the state persist even when the component is not in the DOM. The state isn’t view state, and it isn’t environment state — it’s control state.

Examples of control state include:

  • form state
  • errors from POST requests
  • filters and sort orders
  • selected items

In today’s React apps, control state is often lifted up and treated as view state, or forced into a global Redux store. But while this kind of works, it feels like a missed opportunity. The thing is, React is all about components. And if you can create a <SignUpForm> view component, why can’t you create a store component too?

Store components

The thing about state management code is that it is often easily reusable. The problem is that React components are tied to the DOM, while control state is independent from the DOM.

So let’s take a step back for a moment, and imagine what a store component might look like if it wasn’t tied to the DOM.

To start, a store component would probably publish raw objects instead of rendering state, so it would have a publish() method in place of render(). It could still have state and props properties, and follow patterns we’re familiar with from React components.

Say we wanted to create a store component to represent the state of a single form field — perhaps it would look something like this:

class FieldModel extends Component {
  static defaultProps = {
    defaultValue: ''
  }

  constructor(props) {
    super(props)

    this.state = {
      value: props.defaultValue,
    }
  }

  // The only change is that control components publish objects instead of
  // rendering DOM nodes.
  publish() {
    let value = this.state.value
    let error = this.props.validate ? this.props.validate(value) : null

    return {
      value: this.state.value,
      error: error,
      change: this.change,
    }
  }

  change = (newValue) => {
    this.setState({
      value: newValue,
    })
  }
}

Actually, as you may have suspected, this component is real code. You can see it live on CodeSandbox. The only trick is that it isn’t a React component. It’s a Govern component.

Introducing Govern

Govern is a library for managing state with store components. These are a lot like React components – they can receive props, call setState, and define lifecycle methods. They can be defined as classes, or as stateless functions.

But importantly, store components publish raw JavaScript, so they’re not tied to the DOM.

Store components can be used to handle your app’s environment and control state, including actions, side effects and selectors. This means that Govern can replace redux (or MobX), redux-thunk, redux-saga, reselect, and even recompose.

But Govern works great with existing tools too. For example, this gist demonstrates a simple component that lets you interact with your existing Redux store from Govern.

And the best thing? If you know React, then you already know most of Govern’s API, so you’ll be productive in no time.

The best way to get started is to walk through my guide to React forms with Govern. Then, you can try it out live on CodeSandbox, or get more details from the API Reference.

And if you like what you see or find any issues, let me know with a star or an issue on the GitHub project!

One last thing – I’m using Govern in my own apps, so I’ll be keeping you up to date with my experiences over the coming months. If you haven’t already, make sure you stay in the loop by joining my newsletter. I’ll even throw in a few PDF cheatsheets when you do:

I will send you useful articles, cheatsheets and code.

I won't send you useless inbox filler. No spam, ever.
Unsubscribe at any time.

Thanks for reading, and until next time, happy Governing!

Sensible React Forms, with Govern

Creating forms with React can be a little tricky. Perhaps you decide to use Raw React, and end up repeating the same handler code each time you need a new field. Or maybe you force the non-global form state into a global Redux store. Either way, things get awkward quickly.

But luckily, React forms don’t have to be awkward. In fact, they can be downright easy. And the trick is simple: you just need to understand that form state isn’t like other state.

Three types of state

As it turns out, the problem is that web applications usually have three types of state, and we only talk about two of them.

1. View State

View state includes anything that is associated with the DOM itself. Examples include the state of animations and transitions.

React component state is great is a perfect way to store it, as each React component is tied to a DOM node.

2. Environment state

Environment state includes anything that is relevant throughout your entire application. Examples include the current user’s details, received data, or in-progress requests.

Redux is great at storing environment state, as you generally only have a single Redux store, which can be accessed anywhere via React context.

3. Control state

Control state includes anything associated with user interactions. Examples include the state of forms, selected items, and error messages.

The thing about control state is that it is associated with a specific part of the application, which may be loaded, disposed, or re-used in multiple places. This means that it isn’t environment state, and it doesn’t fit well in a global Redux store.

And while you can put form state in React components, it really doesn’t belong in them. After all, sometimes you want to keep your form state around after the DOM nodes disappear. Sure, you could lift your state up, except now you can’t easily re-use the logic. And isn’t React about reusable components?

But… what if you could define components that weren’t tied to the DOM?

Introducing Govern

Govern is a library for managing state with store components. These are a lot like React components – they can receive props, call setState, and define lifecycle methods. They can be defined as classes, or as stateless functions.

But instead of rendering elements, store components publish raw JavaScript, so they’re not tied to the DOM.

And the best thing? If you know React, then you already know most of Govern’s API, so you’ll be productive in no time. In fact, by the end of this short guide, you’ll be able to build a form with validation and connect it to a JSON API — and you’ll barely need to learn a thing!

So let’s get started by creating your first store component for managing form state.

Defining store components

Govern components are just JavaScript classes that extend Govern.Component. Like React components, they have props, state, and lifecycle methods.

For example, here’s how you’d create a Model component that handles state and validation for individual form fields:

import * as Govern from 'govern'

class Model extends Govern.Component {
  static defaultProps = {
    defaultValue: ''
  }

  constructor(props) {
    super(props)

    this.state = {
      value: props.defaultValue,
    }
  }

  publish() {
    let value = this.state.value
    let error = this.props.validate ? this.props.validate(value) : null

    return {
      value: this.state.value,
      error: error,
      change: this.change,
    }
  }

  change = (newValue) => {
    this.setState({
      value: newValue,
    })
  }
}

Govern components have one major difference from React components: instead of render(), they take a publish() method. This is where you specify the component’s output, which will be computed each time the component’s props or state change.

Subscribing to stores

Now that you have a Model component, the next step is to subscribe to its published values from inside of your React app.

Govern exports a <Subscribe to> React component to handle this for you. This component takes a Govern element for its to prop, and a render function for its children prop. It calls the render function with each new published value — just like React’s context API.

Here’s a barebones example that connects a <Model> to an input field, using <Subscribe>.

import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { Subscribe } from 'react-govern'

ReactDOM.render(
  <Subscribe to={<Model validate={validateEmail} />}>
    {emailModel =>
      <label>
        Email: 
        <input
          value={emailModel.value}
          onChange={e => emailModel.change(e.target.value)}
        />
        {
          emailModel.error &&
          <p style={{color: 'red'}}>{emailModel.error}</p>
        }
      </label>
    }
  </Subscribe>,
  document.getElementById('root')
)

function validateEmail(value) {
  if (value.indexOf('@') === -1) {
    return "please enter a valid e-mail"
  }
}

Try it live at CodeSandbox »

Adding Govern to create-react-app

If you’d like to follow along and create your own app — which I’d highly recommend — then all you need to do is create a new app with create-react-app, and then add govern:

create-react-app govern-example
cd govern-example
npm install --save govern react-govern
npm run start

Once you’ve got Govern installed, you can just copy the above two code blocks into index.js, and you’re set! If you run into any trouble, take a look at the live example.


Did you get it to work? Then congratulations — you’ve just learned a new way to manage state! And all you need to remember is that:

  • Store components extend from Govern.Component in place of React.Component.
  • Store components use a publish method in place of render.
  • You can subscribe to store components with <Subscribe to>.

These three things will get you a long way. But I promised that you’d make a form component, and so far I’ve only demonstrated a field component…

Combining stores

Govern components have one special method that doesn’t exist on React components — subscribe().

When a component’s subscribe() method returns some Govern elements, the component will subscribe to those elements, placing their latest published values on the component’s subs instance property. You can then use the value of this.subs within the component’s publish() method, allowing you to combine store components.

For example, you could combine two <Model> elements to create a <RegistrationFormModel> component:

class RegistrationFormModel extends Govern.Component {
  static defaultProps = {
    defaultValue: { name: '', email: '' }
  }

  subscribe() {
    let defaultValue = this.props.defaultValue

    return {
      name: <Model defaultValue={defaultValue.name} validate={validateNotEmpty} />,
      email: <Model defaultValue={defaultValue.email} validate={validateEmail} />,
    }
  }

  publish() {
    return this.subs
  }
}

function validateNotEmpty(value) {
  if (!value) {
    return "please enter your name"
  }
}

Field view components

One of the benefits of using the same <Model> component for each field is that it makes creating reusable form views simpler. For example, you could create a <Field> React component to render your field models:

class Field extends React.Component {
  render() {
    return (
      <label style={{display: 'block'}}>
        <span>{this.props.label}</span>
        <input
          value={this.props.model.value}
          onChange={this.handleChange}
        />
        {
          this.props.model.error &&
          <p style={{color: 'red'}}>{this.props.model.error}</p>
        }
      </label>
    )
  }

  handleChange = (e) => {
    this.props.model.change(e.target.value)
  }
}

ReactDOM.render(
  <Subscribe to={<RegistrationFormModel />}>
    {model =>
      <div>
        <Field label='Name' model={model.name} />
        <Field label='E-mail' model={model.email} />
      </div>
    }
  </Subscribe>,
  document.getElementById('root')
)

Try it live at CodeSandbox ».

Stateless functional components

You’ll sometimes find yourself creating components that just subscribe() to a few elements, and then re-publish the outputs without any changes. Govern provides a shortcut for defining this type of component: just return the elements you want to subscribe to from a plain function — like React’s stateless functional components.

For example, you could convert the above <RegistrationFormModel> component to a stateless functional component:

const RegistrationFormModel = ({ defaultValue }) => ({
  name: <Model defaultValue={defaultValue.name} validate={validateNotEmpty} />,
  email: <Model defaultValue={defaultValue.email} validate={validateEmail} />
});

RegistrationFormModel.defaultProps = {
  defaultValue: { name: '', email: '' } 
}

Try it live at CodeSandbox ».

Calling a JSON API

Once you have some data in your form, submitting it is easy — you just publish a submit() handler along with the form data. Everything you know about handling HTTP requests in React components transfers over to Govern components.

However, Govern does give you an advantage over vanilla React — your requests can be components too!

For example, this component takes the request body as props, makes a request in the componentDidInstantiate() lifecycle method, and emits the request status via the publish() method.

Note: I use the axios package here to simplify the network code. If you’re following along, you can install it with npm install --save axios.

import * as axios from "axios";

class PostRegistrationRequest extends Govern.Component {
  state = {
    status: 'fetching',
  }

  publish() {
    return this.state
  }

  componentDidInstantiate() {
    axios.post('/user', this.props.data)
      .then(response => {
        if (!this.isDisposed) {
          this.setState({
            status: 'success',
            result: response.data,
          })
        }
      })
      .catch((error = {}) => {
        if (!this.isDisposed) {
          this.setState({
            status: 'error',
            message: error.message || "Unknown Error",
          })
        }
      });
  }

  componentWillBeDisposed() {
    this.isDisposed = true
  }
}

You can then make a request by subscribing to a new <PostRegistrationRequest> element.

class RegistrationFormController extends Govern.Component {
  state = {
    request: null
  };

  subscribe() {
    return {
      model: <RegistrationFormModel />,
      request: this.state.request
    };
  }

  publish() {
    return {
      ...this.subs,
      canSubmit: this.canSubmit(),
      submit: this.submit
    };
  }

  canSubmit() {
    return (
      !this.subs.model.email.error &&
      !this.subs.model.name.error &&
      (!this.subs.request || this.subs.request.status === "error")
    );
  }

  submit = e => {
    e.preventDefault();

    if (this.canSubmit()) {
      let data = {
        email: this.subs.model.email.value,
        name: this.subs.model.name.value
      };

      this.setState({
        request: (
          <PostRegistrationRequest data={data} key={new Date().getTime()} />
        )
      });
    }
  };
}

ReactDOM.render(
  <Subscribe to={<RegistrationFormController />}>
    {({ canSubmit, model, request, submit }) => (
      <form onSubmit={submit}>
        {request &&
          request.status === "error" && (
            <p style={{ color: "red" }}>{request.message}</p>
          )}
        <Field label="Name" model={model.name} />
        <Field label="E-mail" model={model.email} />
        <button type="submit" disabled={!canSubmit}>
          Register
        </button>
      </form>
    )}
  </Subscribe>,
  document.getElementById("root")
);

Try it live at CodeSandbox ».

Did you see how the key prop is used in the above example? Just like React, changing key will result in a new component instance being created, and thus a new request being made each time the user clicks “Register”.

While request components can take a little getting used to, they have the benefit of being able to publish multiple statuses over time — where promises can only publish one. For example, you could publish disconnected or unauthenticated states, along with a retry() action to give the request another crack.

Request components also make it easy to share communication logic within and between applications. For an example, I use a <Request> component within my own applications.

Performance note: selecting data

Govern’s <Subscribe> component needs to call its render prop each time that any part of its output changes. This is great for small components, but as the output gets larger and more complicated, the number of re-renders will also grow — and a perceivable delay can creep into user interactions.

Where possible, you should stick to <Subscribe>. But in the rare case that there is noticeable lag, you can use Govern’s <Store of> component to instantiate a Store object, which allows you to manually manage subscriptions.

Once you have a Store object, there are two ways you can use it:

  • You can access the latest output with its getValue() method.
  • You can return the store from a component’s subscribe() method, and then republish the individual parts that you want.

For example, here’s how the above example would look with a <Store of> component. Note that this adds a fair amount of complexity — try to stick to <Subscribe to> unless performance becomes an issue.

class MapDistinct extends Govern.Component {
  subscribe() {
    return this.props.from
  }
  shouldComponentUpdate(nextProps, nextState, nextSubs) {
    return nextProps.to(nextSubs) !== this.props.to(this.subs)
  }
  publish() {
    return this.props.to(this.subs)
  }
}

const Field = ({ model, label }) => (
  <Subscribe to={model}>
    {model => (
      <label style={{ display: "block" }}>
        <span>{label}</span>
        <input
          value={model.value}
          onChange={e => model.change(e.target.value)}
        />
        {model.error && <p style={{ color: "red" }}>{model.error}</p>}
      </label>
    )}
  </Subscribe>
);

ReactDOM.render(
  <Store of={<RegistrationFormController />}>
    {store => (
      <form onSubmit={store.getValue().submit}>
        <Subscribe
          to={<MapDistinct from={store} to={output => output.request} />}
        >
          {request =>
            request && request.status === "error" ? (
              <p style={{ color: "red" }}>{request.message}</p>
            ) : null
          }
        </Subscribe>
        <Field
          label="Name"
          model={<MapDistinct from={store} to={output => output.model.name} />}
        />
        <Field
          label="E-mail"
          model={<MapDistinct from={store} to={output => output.model.email} />}
        />
        <Subscribe
          to={<MapDistinct from={store} to={output => output.canSubmit} />}
        >
          {canSubmit => (
            <button type="submit" disabled={!canSubmit}>
              Register
            </button>
          )}
        </Subscribe>
      </form>
    )}
  </Store>,
  document.getElementById("root")
);

Try it live at CodeSandbox ».

Note how the above example uses getValue() to access the submit() action, but uses <Subscribe> elsewhere. This is because we know that submit won’t change, and thus we don’t need to subscribe to future values.

Also note how the selector component defines a shouldComponentUpdate() method. If this wasn’t defined, then each update to the from store would cause a new publish — even if the published value didn’t change! Defining shouldComponentUpdate() gives you control over exactly which changes cause a publish — just like with React.

Built-in components

Govern has a number of built-in elements to help you reduce boilerplate and accomplish common tasks. These are particularly useful for creating selector components.

The three built-ins that you’ll use most often are:

  1. <map from={Store | Element} to={output => mappedOutput} />

Maps the output of from, using the function passed to to. Each publish on the from store will result in a new publish.

  1. <flatMap from={Store | Element} to={output => mappedElement} />

Maps the output of from, using the output of whatever element is returned by to. Each published of the mapped element results in a new publish.

  1. <distinct by?={(x, y) => boolean} children>

Publishes the output of the child element, but only when it differs from the previous output. By default, outputs are compared using reference equality, but you can supply a custom comparison function via the by prop.


For example, you could use the <flatMap> and <distinct> built-ins to rewrite the <MapDistinct> component from the previous example as a stateless functional component.

const MapDistinct = props => (
  <distinct>
    <map from={props.from} to={props.to} />
  </distinct>
);

Try it live at CodeSandbox ».

What next?

Believe it or not, you’ve just learned enough about Govern to make useful applications with it. Congratulations!

In fact, I already use Govern in my own projects. I wouldn’t yet recommend it for critical applications, but with your help, it will continue to steadily involve.

If you do find any issues while using Govern, and find the time to file an issue, you’ll be my new best friend. I’m also extremely open to pull requests, and would be happy to help get the word out about any components you’d like to share.

Finally, if you like what you see, please let me know with a star on GitHub! And if you want to hear more about Govern, join my newsletter below – I’ll even throw in a few PDF cheatsheets as thanks!

I will send you useful articles, cheatsheets and code.

I won't send you useless inbox filler. No spam, ever.
Unsubscribe at any time.

Thanks for reading, and until next time, happy Governing!

My experience with React 16

If you haven’t already heard, the big news over the past fortnight is that React 16 was released.

Now I don’t want to waste your time with another “What is React 16?”; the official blog is already very informative. But what I can give you is the story of my experience this week, when I upgraded a large project to React 16.

The short version

If you have a React 15.5 app which doesn’t use deprecated features and doesn’t throw errors, then React 16 just works!

Of course, “it just works” doesn’t make for a very interesting story. So lucky for you, it didn’t just work for me.

Continue reading

JSX, HTML-in-JS and CSS-in-JS

Lately, I’ve been hearing a lot of people talk about JSX as if it is HTML-in-JS. So let me clear something up:

JSX is not HTML-in-JS.

The thing about JSX is that it is just a special syntax for writing plain-old JavaScript.

Each JSX element compiles to a call to a JavaScript function called React.createElement. In fact, you can write apps without using JSX at all; just call React.createElement by itself. Like this:

ReactDOM.render(
  React.createElement('div', {}, "Hello, world!"),
  document.getElementById('app')
)

To repeat myself, JSX is not HTML-in-JS. Yes, it is a way to specify the structure of the DOM. But so is raw JavaScript, like this:

const app = document.getElementById('app')
const hello = document.createElement('div')
hello.appendChild(document.createTextNode('Hello, world!'))
app.appendChild(hello)

If you’re writing an app with JavaScript, you need some way to modify the DOM. JSX is one way of doing it. Raw JavaScript is another. But in either case, you’re still working with JavaScript.

In contrast, HTML-in-JS would look a little like this:

const hello = "<div>Hello, world!</div>"
document.getElementById('app').innerHTML = hello

And sure, this is something you can do. Just like you could chug a bottle of Tabasco. A friend did that once. He was weird. But I digress.

Want to learn more about fundamentals like React.createElement? My Learn React By Itself series was made just for you!

CSS-in-JS

Another thing a lot of people are talking about lately is CSS-in-JS.

Unfortunately, CSS-in-JS is actually exactly what it sounds like. It is literally CSS in a JavaScript file. Let me repeat that. It is actually CSS in a JavaScript file.

The thing is, there are a number of very good reasons we generally put CSS in CSS files (or their LESS/SCSS cousins). For example:

  • Browsers expect to load CSS from CSS files.
  • Editors have syntax highlighting based on file extension.
  • Tooling such as minifiers and linters expect CSS.
  • Existing CSS libraries are written in CSS, LESS or SCSS.
  • CSS files can be cached separately from JS files.

Some CSS-in-JS tools do lots of very clever things to provide workarounds for all of these issues. But if you just use CSS or LESS or SCSS, you don’t need to provide workarounds. It just works.

Of course, there are supposedly a number of benefits. But most of these benefits can be had from more mature tooling like LESS, SCSS, CSS Modules and Webpack (which you’ll need anyway to, you know, put your CSS back into CSS files).

There are some benefits that are unique to CSS-in-JS:

  • You can add things like media queries directly to components, whilst you can’t with standard inline styles. (Yay?)
  • You can share JavaScript variables with stylesheets. Except that this is is massive security hazard.

But all the big names are using it, so it has to be good, right?

So here’s the thing: CSS isn’t perfect. It makes sense that smart people are building alternatives. And the tools do have some compelling use cases — they’ll work with react-native, for instance. But unless you 100% know what you’re getting into, and 100% understand the security implications, I’d wait a little bit longer before jumping on any bandwagons.

I’ve put a few more details on React Armory in my answer to Should I use CSS-in-JS?.

More good news

Keeping up with JavaScript and React can be exhausting — but it doesn’t have to be! The secret is that the basics never change. In fact, my most popular articles are ones I wrote years ago, and they’re still as relevant as ever.

JavaScript fatigue happens, but you can avoid it by sticking to the basics. And that’s why my fortnightly newsletter just focuses on the JavaScript and React fundamentals. So subscribe now — and get a bunch of free PDF cheatsheets as a bonus.

I will send you useful articles, cheatsheets and code.

I won't send you useless inbox filler. No spam, ever.
Unsubscribe at any time.

One more thing – I love hearing your questions, offers and opinions. If you have something to say, leave a comment or send me an e-mail at james@jamesknelson.com. I’m looking forward to hearing from you!

Read more at React Armory

Announcing React Armory

You may have noticed that the updates having been coming a little slower than usual lately. And now I can let you in on the reason!

I’ve been working on a new set of React guides, but with a catch: the code examples on React Armory are live! This means that you can learn React without leaving your browser. In fact, now you can learn React without even leaving your tab.

I’ll be steadily adding more guides over the coming months. But to start out with, I’ve put together a new version of my “Learn Raw React” guide, which starts with Introducing React.

React Armory also includes a number of live examples, where you can test new ideas without configuring anything. For an example, you can play with this Animated Fractal Tree.

As always, I’d love to hear your feedback! Perhaps something in the new guides is unclear? Or maybe there is something you’d like to read about more? Whatever the reason, you’re always free to send me an e-mail at james@jamesknelson.com. I’m looking forward to hearing from you!

Introducing MDXC: A new way to write Markdown for React

Read the README and browse the source on GitHub, or mess around with the live demo.

Markdown is a fantastic tool. It makes writing simple. Markdown documents are plain text, so you don’t need to worry about tags and HTML and all that. You just write. And when you need a <a>, or a <h1>, it’s already there. It’s like magic!

But say you’re writing a React app with pushState, and you don’t want your links to use <a> tags; they break your smooth navigation. You want them to use react-router or react-junctions’ <Link> tags instead. And you’re shit outta luck, because you can’t. Or you couldn’t, before MDXC.

MDXC is a tool to make Markdown and React best buddies. Unlike traditional Markdown, MDXC produces actual JavaScript — not strings of HTML. MDXC lets you embed raw JSX within your Markdown, and even lets you import components and accept props. And to top it all off, MDXC lets you configure how each element is rendered, giving you all sorts of ways to confuse your users and also a few ways to genuinely improve their experience.

If you can’t tell yet, I’m pretty excited about MDXC. So please indulge me and take a gander at this example:

Continue reading

The Haiku Of React Routing Principles

This is the third article in a series on junctions.js. You can read this without reading the others first. But for your convenience, here is part one and part two.

Junctions.js is a router that is based on principles. These principles ensure that Junctions works with React instead of fighting against it. They’re the reason that junctions.js lets you write idiomatic React components instead of some routing-specific dialect of React. And as it happens, they form a haiku:

Components compose

Browsers show “Back” and “Forward”

Get outta’ the way!

But haiku gimmicks aside, each of these principles can make a huge difference to how you route your application. So let’s have a look at each in turn.

Continue reading

Why I created junctions.js

TL;DR? Junctions is a new, composable alternative to react-router. Get it at the junctions.js website!

It was pretty normal day in Tokyo when I received a request from a client. “I’d like this application screen to be a React Component. And I want it to be reusable.”

Given my client’s app was created with React, I naturally said “Yes Sir”. I mean, the best part about React is that components are reusable. What could go wrong?

Continue reading

Do I Even Need A Routing Library?

So you’ve decided to build a React app. It has a few screens, so you need a router. And react-router seems pretty popular, so you npm install it and put together a quick demo. Everything seems fine and dandy!

Or it did, until you googled for some docs the next day. Something seems off. The logo has changed colour from blue to red. And the version number has mysteriously increased from 2 to 4. Huh?

Well at least it didn’t jump to 5. But this makes you think — do I really even need a routing library? Imagine if we lived in a world without JavaScript fatigue where the APIs never change and we could just focus on making awesome stuff. But actually – we kind of do! The browser APIs rarely change. And how much longer could it take to just use them instead of some complicated library?

Continue reading

The 5 Types Of React Application State

I don’t know about you, but when I started writing React apps, I struggled to decide where my state should go. No matter how I re-arranged setState calls, things never felt quite right.

"Messy state"

And maybe that is why I got so excited when I found Redux. Redux gave me a single place to put all my state. Which sounded great in theory.

"What if"

But then I realised that having one spot to put things doesn’t necessarily make them easy to get to.

"Still messy"

It turns out that I needed more than just a place to put things. I also need a system for putting them in the right place.

"Banzai!"

For me, that system came from splitting my state into five categories. It turned the problem of deciding “how does this piece of state relate to all the other state”, into the problem of deciding “what type of state is this”. And as it turns out, this is a whole lot easier.

Continue reading