There seems to be a big blind spot in these Real World React+Redux tutorials when it comes to forms.

For example, say I have a page with reviews on it. So there's a Component that handles editing a review. Where does the state for all the form inputs go? Does it go in the Redux store? If it does, then every time the user types a letter you get an event, which goes walking backward through the component tree until it hits the review editor Controller, which generates an action, which dispatches to the store, which gets reduced causing a state change, which then percolates back up through the Controller/Component tree to finally add that letter to the input. That walking back and forth is bad enough on its own, let alone generating an entirely new state (because the state is immutable) for every single letter the user types. It's inefficient, and it adds noise into the action log.

The alternatives seem to be storing the state in the component in which the typing is happening, or in the parent Controller, and then only generating update actions against the store when some "finished typing" event occurs (i.e. onBlur or timeout). Of course this seems to go against the idealistic implementation of Redux where all the state is stored in that one state object and it's immutable.

My point being, I haven't stumble across a "real world" tutorial that goes over this stuff. I wouldn't quibble about that normally, as I'm happy to play around and find the solution on my own, but this feels like such a common and important task (what website doesn't have forms of some kind?) and the performance and maintenance implications of how this is implemented seem large. So it would be nice if there was a "We built this huge web app using React and Redux, this is how we ended up doing forms and it works well for us" article.

I agree with your point and disagree with redux-form being a valid solution. redux-form creates a very restricted and crippled API for getting form data into a redux state object and does so at the expense of the spirit of React's componentized model. Any redux-form state needs to be isolated under a special root object specifically for forms. You can't just mount some existing part of your state object into a form because of this. Not to mention redux-form properties have a whole bunch of other "glue" properties in addition to the actual value of the form.

I question whether people use it in large scale production. This is one of the huge downfalls of redux. It makes some things easier, but it makes the most fundamental stuff (editing form fields) extremely contrived. This is the main reason I don't see react+redux as a true answer to the challenges of SPA development but a very rough, intermediate step which needs to be re-thought while putting into consideration the most common use cases.

I've used it in a couple of form-heavy production projects and found it to be good, I find the API pretty easy to work with and it handles things like async validation pretty nicely (I use it in combination with yup for validating the form object: https://github.com/jquense/yup). I can honestly say it has almost made working with forms enjoyable ;)

A definite high point of my time with it was when a requirement came along to allow users to resume signup - because all the form state was in the Redux store already, it was simply a case of serializing that and putting it in localStorage (or wherever), then reloading it as the initialState.

There are performance issues to be aware of if your form gets too large, caused by the "top down re-render" effect of having the top level ReduxForm HOC connected to the form state and therefore re-rendering on every keystroke - often these can be solved by splitting the form into sub-components with appropriate shouldComponentUpdate etc., but this isn't a perfect solution - see https://github.com/erikras/redux-form/issues/123 for a lot of discussion. The new v6 API aims to solve this, by removing the need for a single top level component: https://github.com/erikras/redux-form/tree/v6

I've been intending to write up my experiences and how I've been working with it, but decided to hold off until the v6 API stabilised, so that I wasn't giving outdated advice. Happy to answer any questions in the meantime!