Here's what you can do to make migrating your forms to Redux easier in the future

01 Oct 2017

Cover image: Here's what you can do to make migrating your forms to Redux easier in the future

You know you don't need Redux for your form state... yet. Requirements change and apps evolve. You can't always know in advance. What was perfectly fine to store in the local state might need to be moved to Redux.

Oh, and it can be painful to migrate to Redux.

But it can also be smooth... if you do certain things.

Actually, just one

Make small 'action reducer' functions. They would take current state and some details about the action, and return the new state.

function changeEmail(state, newEmail) {
  return { ...state, email: newEmail };

changeEmail(state, ""); // => returns state with the new value of email

They can be literally used with the functional form of setState:

handleEmailChange = (evt) => {
  this.setState(state => changeEmail(state,;

If you've never passed the function to setState, don't worry. There's a section about it in React docs. Basically, instead of passing the new state to setState, you can pass it a function which would accept the current state and return a new state.

Logically, this.setState(fn) is similar to doing this:

const newState = fn(this.state);

Then, to migrate this to Redux, you'd only need to do a few things:

  1. Instead of calling setState(state => changeEmail(state, ...)), you would dispatch an action: this.props.onChangeEmail(...);
  2. Instead of getting the current values of fields from this.state, you'd use this.props.
  3. The changeEmail function trivially becomes a branch in the reducer:
function loginFormReducer(state, action) {
  switch (action.type) {
    case "changeEmail": {
      return { ...state, email: action.newEmail };

Going a bit futher

You can go further and create a local "reducer" in your component.

Here's a general idea:

Since actions are often accompanied by some relevant data (like the new field value), we need something more than string actions ('increment'). We need action objects ({ type: 'something', otherRelevantData: 42 }).

function changeEmail(newEmail) {
  return { type: 'changeEmail', email: newEmail };

class Form extends Component {
 // ...
  reduce = action => this.setState(state => this.reducer(state, action));

  reducer = (state, action) => {
    switch (action.type) { // note we're switching by action.type
      case 'changeEmail': return { ...state, email: };

  render() {
    // ...
      onChange={evt => this.reduce(changeEmail(}

If it seems really close to Redux, that's because it is.

It would be trivial to switch from local state to Redux when a form manages its state this way:

  • changeEmail would be left without changes, and would be connected by react-redux;
  • Instead of having reducer in the class, it would become a Redux reducer;
  • Instead of doing this.reduce(changeEmail(...)), you'd do this.props.onChangeEmail(...).

Think your friends would dig this article, too?

If you need a mobile app built for your business or your idea, there's a chance I could help you with that.
Leave your email here and I will get back to you shortly.