News for hackers. Stuff that matters.
Re:A SoundCloud client in React and Redux by fpgaminer on Sunday June 12, 2016 @07:31PM (#11890861)
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.

Re:A SoundCloud client in React and Redux by antjanus on Monday June 13, 2016 @12:22AM (#11891723)
We use Redux where I work and we deal with a TON of forms, many of which are controlled completely separately from each other. Oh and it's an Angular 1 app and in production.

Basically what I've learned is that you have to distinguish between global and local application state. Redux doesn't have to know EVERYTHING that's going on in the application.

That means that when you're editing a piece of text, it depends on what you want from it. Are you showing word count in several places that aren't contextually related? (like a total word count up top on your page, and a local word count). If so, run it through Redux on every key down/key up event. Are you NOT using that information anywhere? Then skip Redux and pipe that edited text through only when a user hits "save".

The entire point of Flux was to have one source of truth for shared data in your app. If you're not sharing information, it doesn't have to be shoved into Flux/Redux. The example the FB developers brought up was reading messages. You have like 5 places that unread message count shows up: the little chat bar on bottom if you haven't read a message from a recent contact, notification bar up top, chat sidebar, and left sidebar (I think). Doing anything in any of those places should trigger a change: unread count drops when you open a chatbox with a person that left you a message for instance.

But if you're writing a message and you're looking at your character count (like on twitter when you're writing a tweet), that data doesn't need to be shared. It just stays in that textarea component.

I hope that makes sense! :)

Re:A SoundCloud client in React and Redux by stickperson on Monday June 13, 2016 @01:37AM (#11891899)
Autocomplete is another good example. Instead of having my autocomplete API call go through the whole dispatch -> reducer flow, I just update my component's state when I get a response.
Re:A SoundCloud client in React and Redux by joshuacc on Monday June 13, 2016 @01:46PM (#11895715)
Yay! Another person using Redux with Angular 1. I've found it's a surprisingly nice combination. :-)
Re:A SoundCloud client in React and Redux by waffleau on Sunday June 12, 2016 @09:03PM (#11891135)
This is something that tripped me up when I first started learning Redux too, and it would be great if there were more articles about what to do with the bits that don't really fit nicely into the model.

My personal take is that the Redux state tree is for managing state that other components care about, i.e. if this changes, does something outside of this need to know? In the form example, there are few cases where we care about what is being typed as it is being typed (maybe autocomplete). We generally only care about the complete input. This could even be taken to the next level and we could say we only really care about the contents of a form once it has been submitted.

To think about it another way,: what state would we like to keep if the page was refreshed? Many UI elements may contain state we don't really care about outside of the component, such as drop-down menus, accordions, etc. There are things which constitute global state, and there are things that really are just local state. Why make them global?

Ultimately, the goal of Redux is to make reasoning about the state of an application easier, and to encourage better architecture. If pushing certain bits of state into the tree makes this harder, there's no reason to try to force it to fit the pattern.

I'm sure there are good arguments for why everything should be in the global state, but I just haven't found it to be practically beneficial.

Re:A SoundCloud client in React and Redux by Renner1 on Sunday June 12, 2016 @08:30PM (#11891040)
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.

Re:A SoundCloud client in React and Redux by girvo on Sunday June 12, 2016 @08:36PM (#11891051)
> I question whether people use it in large scale production.

We tried to, and removed it within 4 weeks of development with it, for all of the reasons you mentioned. It conceptually doesn't map to our Redux model, and new developers struggled with it because of that. I ended up writing my own "wrapper" to do something similar, but to be honest for most of our form state it is handled within the components themselves (via this.state and friends) and only sent to Redux once validated. React's built-in state handling is still useful, specifically for these sorts of things.

Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @08:57PM (#11891106)
What are the pros/cons of setstate vs a batched state subtree for each component and an aggregate state subtree for each component that matched each form parent, specified by a string to a higher order component for the parent form and a string for each component used to model html5 form inputs?
Re:A SoundCloud client in React and Redux by acemarke on Monday June 13, 2016 @01:41AM (#11891906)
Ah... you lost me on that statement. Can you give me an example of what you're picturing?
Re:A SoundCloud client in React and Redux by acemarke on Sunday June 12, 2016 @08:43PM (#11891070)
I'd be interested in seeing what you put together. Is that available somewhere?
Re:A SoundCloud client in React and Redux by girvo on Sunday June 12, 2016 @08:45PM (#11891076)
Not yet, but it will be!

https://github.com/studionone/ is where it will live, plan is to release it this week, all things going well.

Re:A SoundCloud client in React and Redux by acemarke on Sunday June 12, 2016 @08:56PM (#11891100)
Cool. I'll keep an eye out for it!
Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @08:49PM (#11891084)
Also tried redux form and while the creator is very talented it was just more trouble than it was worth for our team. There's a real opportunity to create a sound abstraction to forms with react and redux right now. I've investigated this heavily and no existing approach works how I'd like.

What I want is a higher order component for a given form parent specified by a string, with higher order components for all common html5 form types which are stored in a state tree child node based on a string for the form parent and each component which encapsulates form elements, and rolls up small change events to avoid event log spam.

I originally thought a json or other dsl solution would be ideal, but that ends up being an integration and interoperability headache. Jsx as a dsl works better than json as a dsl for ui in my experience. The big question is where to store the "batched" changes before being rolled up.

I think rather than component setstate, perhaps a sub tree in the redux store with its own subtrees could exist with a specific prefix that could be hidden in the redux devtools chrome extension to avoid the spam problem. I rather like this solution, as it would make react and redux forms beat the simplicity of angular 1 forms with all the benefits react and redux bring. Would other people use it? Anything like it exist already? Maybe I'll create this...

Re:A SoundCloud client in React and Redux by davidkpiano on Monday June 13, 2016 @12:07AM (#11891672)
You should take a look at https://github.com/davidkpiano/react-redux-form - solves many of your problems listed (batches actions when possible to prevent log spam), and V1.0 will be even simpler/more performant.
Re:A SoundCloud client in React and Redux by davidjnelson on Thursday June 16, 2016 @05:46AM (#11915056)
I did after reading your comment. Sweet approach and some quite clever algorithms in the implementation. Nice work! I'll have to play with it. If it's not quite the api I need maybe I'll open an issue to discuss a potential pull request. Thanks :-)
Re:A SoundCloud client in React and Redux by tomduncalf on Monday June 13, 2016 @05:47AM (#11892644)
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!

Re:A SoundCloud client in React and Redux by magnusson on Monday June 13, 2016 @02:11PM (#11895905)
FWIW redux-form v6 changes this: https://github.com/erikras/redux-form/releases

I've been using redux-form in large production app, btw, and have mostly found it nice, but am looking forward to migrating to the new version.

Re:A SoundCloud client in React and Redux by ht85 on Sunday June 12, 2016 @10:00PM (#11891326)
Most of the time I don't feel like performance is an issue as long as all your components use PureRenderMixin. Unless it takes over 20-30ms to render, the difference is not noticeable.

The problem as others have said is that it pollutes history, and that it is very CPU cycle hungry, bad for anything running on battery.

Nowadays I tend to use onBlur instead. There are two scenarios:

1) The form is the only source of change for the data. In this case just update the global state onBlur.

2) Other things affect the form value, so you need controlled input. In this case, onChange updates the local state. onBlur updates the global state and set the local state to null. Use `<input value={localStateValue !== null ? localStateValue : globalStateValue}/>`

Re:A SoundCloud client in React and Redux by davidkpiano on Monday June 13, 2016 @11:56AM (#11894892)
I'm working on it, I promise!

I have been doing a LOT of work on forms in React and Redux, and have been putting all of my ideas into a library called React-Redux-Form: https://github.com/davidkpiano/react-redux-form

The premise is simple - your model state shouldn't be intertwined with your form state, and everything should be "vanilla Redux" -- that is, everything related to form state should be represented by actions and reducers, and not by some black-box API hidden inside a decorated component.

Version 1.0 is still in the works, but promises a lot of things such as making it MUCH simpler to get up and running with configuring the Redux store for forms, and also making smart optimizations that greatly improve performance.

My goal is to make forms as easy to implement as it was in Angular, and offer full flexibility to the developer to handle forms of various complexity.

Re:A SoundCloud client in React and Redux by JasonSage on Sunday June 12, 2016 @07:43PM (#11890900)
One small nitpick

> let alone generating an entirely new state (because the state is immutable)

Assuming you're talking about the redux state, this is only if the state changes. Dispatching an action to change the state of your form should cause the form's entire state tree to change at most, and possibly as few as one or zero objects. All those other redux reducers that just return the previous state are not going to have any performance impact.

In effect, your state is immutable but you're only getting "new" state references for a small portion of the state atom, very cheaply.

Re:A SoundCloud client in React and Redux by idbehold on Sunday June 12, 2016 @09:07PM (#11891147)
It all depends on what's going on in the render method and/or shouldComponentUpdate.
Re:A SoundCloud client in React and Redux by lopatin on Sunday June 12, 2016 @08:19PM (#11891014)
For basic forms, where you're not doing something weird, why would intermediate form state need to live in Redux? Local React state seems best for that.
Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @09:03PM (#11891137)
Are there any cons to this approach? For me, having to implement setstate manually, not having full undo/redo/time travel debugging as an option/not being able to rehydrate the app from any state snapshot, along with the cognitive overhead of keeping state in sync in two places, one of which is mutable, are the big downsides.
Re:A SoundCloud client in React and Redux by brentm on Sunday June 12, 2016 @09:45PM (#11891285)
I agree with this. I've tried redux-form and just manually handling it with Redux but letting the form data live in the form's component state felt the most clean to me.
Re:A SoundCloud client in React and Redux by firasd on Sunday June 12, 2016 @08:55PM (#11891098)
Your concerns about input events moving up and down the component tree seem misplaced. It’s what happens when you use React anyway (unless you’re only using local component state); putting these input values in the Redux store only makes things simpler.

As for the fact that it changes the state and adds noise to the log… these seem like aesthetic judgments on your part. Why is changing an input “noise”? It’s an important part of the data on the page.

Re:A SoundCloud client in React and Redux by acemarke on Sunday June 12, 2016 @09:08PM (#11891150)
No, it's a pretty valid concern. If you assume controlled inputs, and you also tend towards putting all your state into Redux, that's exactly a use case issue you can see - every keystroke would, in theory, require a full round-trip through the store and back to the component, and also causing at least a `mapState` call and comparison for every other connected component along the way.
Re:A SoundCloud client in React and Redux by firasd on Sunday June 12, 2016 @09:14PM (#11891174)
Here is a GIF of me putting input state (and general form state) in the Redux store: http://i.imgur.com/QRDH1Sy.gifv

Yes, if the keystrokes are not debounced it generates many actions. But my point is that concern about the ‘efficiency’ of moving events through components when using Redux is nothing compared to the byzantine way I had this implemented before using Redux. Trying to build forms in React without Redux or some other state solution, by just using setState and moving events and state up and down the component tree, will make you tear your hair out.

Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @09:02PM (#11891133)
For me the batched changes are useful, but single character changes can make the event log overly verbose.
Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @09:51PM (#11891303)
For the downvoter, you don't find single character changes overly verbose in the redux devtools monitor?
Re:A SoundCloud client in React and Redux by acemarke on Sunday June 12, 2016 @08:28PM (#11891034)
First: Redux is _not_ dogmatic about putting every last bit of your state into Redux. It is entirely up to you how much or how little goes into Redux. (This question comes up all the time, which is why I added it the the Redux FAQ [0] ).

So yes, there are absolutely times when it makes sense to keep data, such as frequent user input updates, in local component state, and only dispatch an action later. In fact, a while back I put together a wrapper component that does exactly that [1]. Made a few tweaks since then that I haven't added to the proof-of-concept in the gist, but the basic idea is there.

I do have a number of articles on React and forms in my React/Redux links list [2], but at the moment I don't think any of them specifically deal with Redux usage. Might be interesting to look through some of the apps listed in my real-world Redux apps list [3] - the Jenkins UI and Wordpress Admin Page apps might be relevant.

I will say that while Redux Form [4] is probably the most widely used Redux form logic library at the moment, React Redux Form [5] is another option that looks good. In fact, the current Redux Form 6.0 beta API is heavily inspired by RRF's API. My Redux addons catalog also has a page listing a number of other options of varying kinds [6] (none of which I've used myself, btw, just catalogued).

All that said, yeah, would be great if someone were to write up a larger, more in-depth article about dealing with forms.

[0]: http://redux.js.org/docs/FAQ.html#organizing-state-only-redu...

[1]: https://gist.github.com/markerikson/554cab15d83fd994dfab

[2]: https://github.com/markerikson/react-redux-links/blob/master...

[3]: https://github.com/markerikson/redux-ecosystem-links/blob/ma...

[4]: https://github.com/erikras/redux-form

[5]: https://github.com/davidkpiano/react-redux-form

[6]: https://github.com/markerikson/redux-ecosystem-links/blob/ma...

Re:A SoundCloud client in React and Redux by tomtau on Sunday June 12, 2016 @08:04PM (#11890964)
100% agreed, the current standard seems to be redux-form but I've never heard of any serious production build using it.
Re:A SoundCloud client in React and Redux by Vekz on Sunday June 12, 2016 @08:04PM (#11890963)
Re:A SoundCloud client in React and Redux by Lazare on Sunday June 12, 2016 @08:08PM (#11890972)
Everyone basically just uses Redux Form (http://redux-form.com/5.2.5/) as near as I can tell; it really works well.

It basically works as per your first guess: Everything goes in the store. And no, it doesn't really have any performance or efficiency issues. Try it out and see. :)

Re:A SoundCloud client in React and Redux by Koromix on Sunday June 12, 2016 @08:51PM (#11891087)
The overhead for a simple textarea seems significant. On Firefox there are stalls (up to 500 ms) if I type "fast". I've tested the form on http://redux-form.com/5.2.5/#/examples/simple?_k=8ukhm8 (specifically the textarea).

Here is the CPU time graph during my tests: http://imgur.com/we9uGQ7

EDIT: OK apparently it's not accurate, see comment below.

Re:A SoundCloud client in React and Redux by fpgaminer on Sunday June 12, 2016 @09:44PM (#11891279)
Confirmed; just tested on my machine (Firefox, i7-3632QM @ 2.2GHz) by mashing on the keyboard. CPU spikes to 100% on one core and results in stalling.

In contrast the React+Redux app I'm working on uses the local Controller/Component state method and mashing on the keyboard there gave ~20% CPU.

I never would have imagined that Redux Form would lag on a desktop/laptop. I was more concerned that mobile performance would suffer. It's kind of impressive that a simple form can lag a desktop browser...

Re:A SoundCloud client in React and Redux by groovytime on Sunday June 12, 2016 @09:59PM (#11891324)
He has redux dev tools enabled, hence the performance issues.
Re:A SoundCloud client in React and Redux by Koromix on Sunday June 12, 2016 @10:32PM (#11891399)
Indeed it behaves much better on a demo I found elsewhere, sorry for the inaccurate comment.
Re:A SoundCloud client in React and Redux by iyn on Sunday June 12, 2016 @08:22PM (#11891020)
For improved performance (especially on big/complex forms) I suggest looking/using v6 (technically still in alpha, but stable).
Re:A SoundCloud client in React and Redux by davidjnelson on Sunday June 12, 2016 @09:07PM (#11891146)
While a super cool and important project, it's a ton of work to integrate into an app when you have maybe 3 sets of radio buttons to deal with, such as when doing an incremental migration refactoring.
Re:A SoundCloud client in React and Redux by sorahn on Monday June 13, 2016 @01:59AM (#11891947)
>it's a ton of work to integrate into an app when you have maybe 3 sets of radio buttons to deal with

Untrue. It easily reduces the amount of code in your component, and actually gives you the ability to make your FormComponent as a stateless component.

https://gist.github.com/sorahn/6fac9f4717a81c96cd97e2bcc86a1...