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.
- Draw out the HTML (don't worry about using React components yet) in JSX - single quotes,
className
instead ofclass
as an attribute,style
as a camelCased object. Now return it in the render method of a React component. Let's call it "MyForm", soclass MyForm extends Component
(where Component comes from importing from react). - 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 ofonSubmit
and callthis.prop.onSubmit()
in your local callback. - 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. - 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. Thenthis.context
will have our store/dispatch (declare static contextTypes withstore
, callsuper(props, context)
in the view's constructor). - 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. - 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.