Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Populate react-redux-form With Dynamic Default Values

DZone's Guide to

How to Populate react-redux-form With Dynamic Default Values

In this livecoding/article tutorial, you'll learn how to create auto-populated inputs on a web page using the React framework along with Redux.

· Web Dev Zone ·
Free Resource

Start coding something amazing with our library of open source Cloud code patterns. Content provided by IBM.

Here's a problem that took me embarrassingly long to solve: How do you populate dynamic values into a react-redux-form?

First of all, react-redux-form is not the same as redux-form. They're similar but not the same. The internet is confused about this issue, and that makes googling hard.

Second of all, we're talking about a form driven by Redux. Pre-filling it with default values should be as easy as filling out its Redux state. Right?

Well, forms live in their own reducers that you don't have direct access to. They use a bunch of internal states to mark inputs as dirty and focused and whatnot. It's a mess.

Let's start at the beginning.

A Simple react-redux-form

Here's a simple form built using react-redux-form. It has two input fields. When you Submit, it outputs your values to the console.

See the Pen ReactReduxForm - Quick Start by Swizec Teller CodePen.i0.

Borrowed the code straight from @davidkpiano's official Quick Start example.

Our form starts with a model and a Redux store:

const initialUserState = {
  firstName: '',
  lastName: '',
};

const store = createStore(combineForms({
  user: initialUserState,
}), applyMiddleware(thunk));

initialUserState describes the shape of a user and combineForms creates a special reducer. That reducer takes care of driving the UI for our form and storing values.

You'd think you could add default values to initialUserState, and you can. Hold that thought... let's make sure we understand react-redux-form first.

The form itself comes in as a React component using <Control> elements from react-redux-form.

class UserForm extends Component {
  handleSubmit(values) {
    console.log(values);
  }
  render() {
    return (
      <Form
        model="user"
        onSubmit={(values) => this.handleSubmit(values)}
      >
        <div className="field">
          <label>First name:</label>
          <Control.text model="user.firstName"  />
        </div>

        <div className="field">
          <label>Last name:</label>
          <Control.text model="user.lastName" />
        </div>

        <button type="submit">
          Submit
        </button>
      </Form>
    )
  }
}

handleSubmit is the function we call when a user submits either by pressing the Submit button or hitting Enter. In our case, it prints values to the console.

The render method uses a <Form> component from react-redux-form. It comes with all the necessary Redux wiring so we don't have to worry about that.

We use the children of that component to define how it renders. In our case, that's two divs, some labels, a submit button, and two <Control.text> components.

<Control.X> components come with all the necessary wiring for our form to work. They'll handle focus, blur, default values, matching to correct parts of our model, and so on. Everything we don't want to worry about manually.

Wonderful!

Static Versus Dynamic Default Values

Back to that obvious thought. Why can't you just use initialUserState to define default values?

You can. As long as your default values are static.

Let me explain.

Your default form values are static if you know them in advance. Like when you're writing your code. This is pretty rare.

What if you're building an edit form? You can't know values for your form until the user chooses what they're editing.

And that's when trouble begins.

Fill react-redux-form With Dynamic Default Values

@lukeed05 helped me find the solution during livecoding. Thanks, mate.

Here's how you do it:

react-redux-form comes with a bunch of model actions. Actions, its reducer, understands. Actions is what it can use to do special things, like populate your form.

See the Pen ReactReduxForm - Dynamic Default Values by Swizec Teller on CodePen.

Tap the "Change Defaults" button to pick a new random user. Its name will populate the form, and you can edit it to your heart's content.

To make that work, we used a Redux action generator called actions.merge. It lets us merge the form model with a new set of default values.

First, we connect our UserForm component to Redux.

const mapDispatchToProps = {
  setDefaultUser: (values) => actions.merge('user', values)
}
const ConnectedForm = connect(null, mapDispatchToProps)(UserForm);

The usual stuff. Use connect to connect to Redux, there are no props we need from state, and we use mapDispatchToProps to add a dispatch function called setDefaultUser.

setDefaultUser is a curried application of actions.merge. This takes a value object and merges it with the user model in our store.

I wired it to an onClick callback in this example so you can try it multiple times.

 changeUser() {
    this.props.setDefaultUser(
       randomUsers[Math.floor(Math.random()*randomUsers.length)]
    )
  }

Another approach you can use is to call this action in componentDidMount. That gives you true defaults - a form populated as soon as a user sees it.

Happy hacking!

Code something amazing with the IBM library of open source blockchain patterns. Content provided by IBM.

Topics:
web dev ,react ,redux ,javascript framework

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}