Creating forms with callbacks in React+Redux

In React, you have some simple/dumb components which are just html and other components and maybe render some values which are passed in. It becomes a little trickier when you want to add some functionality to the component, such as form elements - inputs and buttons and submit actions. What I mean by "forms with callbacks" is that you want to execute some JavaScript and also change state in your React app, but do so without giving direct access to state to the component. Instead here's one way to do it.

  1. Draw out the HTML (don't worry about using React components yet) in JSX - single quotes, className instead of class as an attribute, style as a camelCased object. Now return it in the render method of a React component. Let's call it "MyForm", so class MyForm extends Component (where Component comes from importing from react).
  2. Any form elements which will trigger events (like submitting your form) will use the normal callback functions like onSubmit or onClick and call a function defined in the React component, next to render(). E.g. <form onSubmit={this._onSubmit.bind(this)}>. Then you'll define a class method called _onSubmit and you can call any callbacks passed in from a parent as a prop (e.g. you could accept a prop of onSubmit and call this.prop.onSubmit() in your local callback.
  3. Now you need a parent component (like a "view" component if you're separating containers and views) which will use your form component and pass in the props. So somewhere in the view component, you use MyForm like <MyForm prop1 prop2 prop3... />. Anyways let's call it "ParentView". So you setup your ParentView React component in /views/ParentView.js which renders and returns MyForm along with other sibling elements.
  4. ParentView needs to pass all those callbacks to MyForm as props (i.e. as attributes of the MyForm element). Each of those callbacks can be locally defined methods too, as wrappers. Now we can dispatch Redux actions (and action creators) in our class methods because we will connect() up dispatch. Then this.context will have our store/dispatch (declare static contextTypes with store, call super(props, context) in the view's constructor).
  5. The parent view will need to import all the action creators. You'll use bindActionCreators to bind the store/dispatch to your imported action creators, combined into an object. The callbacks defined in the parent class dispatch actions when events are triggered in children.
  6. Use react-router to call your ParentView and you can now look at your React form.

Note: It's not good practice to overuse React's "context" (defined in contextTypes) in this way.