Angular Forms with Redux - angularjs

Looking for some advice when working with Redux, and Angular. I've been researching Redux for the past couple of days and really think its a great way to store application data. The part I'm having trouble with is whether to persist everything within the store or only certain parts. Ideally, I think the entire application should be running through the store, but for forms this seems very tedious.
For example, lets say I'm working with a form to add a new product. Here are some of my pain points.
I would like to keep the User Reducer (store) separated from the actual form state. Should I create a separate form reducer per component?
Having to persist every input field back to the store sounds like a lot of work. I've seen the library redux-form simplifies this, but is intended for React.
Anyone have any good advice when it comes to creating forms in Angular with Redux?

The answer is "it depends". Also, the assumption is that you''re convinced of the benefits of one-way data flow and redux, so prefer redux over two-way data binding if given the choice.
Uber-simple form (no validation, no complex relationships with other state). Then you could "go naked" and directly hook up the inputs to redux. In our use case, we actually decided to go with Angular forms because we figured it handles edge cases (IE and safari mobile).
Don't need every form change in redux state. Then the form submit can dispatch an action to update redux state. Things get tricky if the form needs to change in response to redux state. See below.
You do need every form change in redux state. Angular forms do not have a form#ng-change, so one strategy is to attach an ng-change to every input that dispatches an action to update the redux state. (Yes, it is error prone because it easy to forget to use ng-change, meanwhile the app appears to work.) Again, things get tricky if the form needs to change in response to redux state. See below.
Updating the form in response to redux state change
The common use case is actually very simple. A concrete example will help---suppose the form tracks app settings, meanwhile app settings exist as redux state. That is, there is a two-way data binding between the Angular form and the redux state. This is probably the common use case.
In this case, the solution is to proceed as before: update redux state from the Angular form by dispatching update actions, and update the Angular form from redux state via #mapStateToThis.
Angular ----dispatch actions-----> Redux
Form <----mapStateToThis-------- State
The only gotcha is to not pass the Redux state directly to the Angular form i.e., deep clone the data or use ImmutableJS.
The other common use case is to implement a "form reset", that is, reset the form to a "pristine" state after pressing a button, for example. Again, a concrete example will help:
Suppose that app state (redux state) tracks whether the state is pristine via a flag app.pristine. (To clarify how app.pristine works, it works as expected, that is, it changes to false as soon as any value changes, and changes to true only when explicitly set to true.)
First, as far as I know, Angular doesn't automagically keep track of the "initial" state. You have to do it yourself and you may as well put that state in redux. Then, the initial form values are just the app settings when app.pristine is false. (If you're thinking of putting this in #mapStateToThis, don't. Doing side effects in a transform function seems weird.) A better way is to use an asynchronous action, namely the form onChange listener:
// thunk example
onFormChange(newForm) {
return (dispatch, getState) => {
const appSettings = getState().appSettings;
const appIsPristine = appSettings.pristine;
// this will fire once because the next action will set it to false
appIsPristine && dispatch(initForm(appSettings)));
dispatch(updateAppSettings(newForm));
};
},
The reset action works as you would expect (which I won't outline).
To conclude, I should add that the above assumes that only the Angular form can dirty the app settings---otherwise, the initial form values may never be stored. If that's the case, then one idiomatic solution is to create a custom middleware that sets the initial form value whenever app.pristine changes to true. (Alternatively, use an Angular watch.)

Related

Why should you dispatch an action to update the state and not update the store directly in react/redux?

Explain briefly about... Why should you dispatch an action to update the state and not update the store directly in react/redux?
Redux is a dataflow pattern that is event (=action)-based. Only actions lead to store changes. Also, those have to happen without changing the old state, but by creating a new one.
This is a base assumption and un-bendable rule, because that is the purpose of Redux - moving applciation logic out of your UI layer.
All tooling depends on that assumption - e.g. react-redux will only check for new state after a dispatch and it will do so by comparing current and last state value.
If you want to directly modify it, you simply have gone for the wrong library.
There are libraries that allow for such things, like mobx or valtio, but it will not work with Redux.

Can you create a react redux store interceptor to watch a property?

Let's say i have a property in the store called state.items.byId each time this is updated (various parts of the application) i want to intercept the value before i'ts updated and run a function to update some properties on it before it's updated.
I don't know the terminology and i'm quite new to redux, but if someone could point me in the right direction that would be great!
I have searched and found redux-watch but i'm not 100% sure if this is the right approach
below shows the data flow in a redux application. View dispatches an action, the action
object is a blue-print telling the reducer what changes it needs to make to the store state. Any
change in the redux store state needs to pass through this cycle.
redux-watch provides you a subscription based mechanism notifying you after a property is
changed. If you want to intercept a property before its changed you can write a custom
middleware and handle any side-effects inside it.

get input value from props

In react they say you can't change props directly (or at least you shouldn't).
But I wonder what should I do if I have an input in component and I have a value that comes as props?
I just wanted to know whether it's okay and what is the better way of doing this?
// product.amount comes from props
<input type="number" value={product.amount} onChange={(e) => onChangeProductAmount(e)}/>
so it seems like I want to change product.amount when input changes, but it is in props, so I shouldn't do it.
What should I do then?
Since the props are from the redux, you can change them in redux way only: calling an action creator that will fire an action.
There are packages that do that. I am not familiar with redux-form, but as far as I remember, it is one package that is maintaining the form state in redux. You can implement a similar thing yourself.
I do things differently: I use local state for controlling the input. When the user clicks 'submit', and if the values are valid, I call the action creator which fires the action that changes whatever needs to be changed in the redux store. However, these changes are not reflected directly in the form, as you want to do.
Some time ago I implemented a small app that handles forms this way. You may find it helpful: https://github.com/rahamin1/reactstrap-form

React Redux, component internal state sync

This is a bit complicated so I'll try to put it as simple as possible.
I have a pretty much complicated reusable component in my app.
Basically, it is a large table with many editing options.
Since this component should be reusable, my thought was that it should manage it's own state.
It also makes sense because this component's business logic is pretty much complicated, and by using redux, I'll probably have to repeat some crazy boilerplates.
On the other hand, this component should be able to have some default data loaded to, and finally, this component is in some cases a part of a form, so I sohuld be able to extract it's data and send it to the server.
Redux can really help with the last two tasks - if I had an easy way to store all component changes in the store, I could easily load the default data from there (because my component will be fully controlled), and it will also be easy to extract data from the store when sending to server.
Although, it has a lot of boilerplate, and I'm not feelinng comforotable to write a componenet specific logic in my reducers, since ideally, they could manage themselves.
Any more ideas about that?
I had one idea that seems to be working, though I am not sure how good it is:
Have a "dataKey" prop to handle default data prop changes, and derive the state from the data
Use some submit callback to extract the data and send to server
Any more thoughts will be very helpful, thakns!
It's hard to provide an extract answer as your question is kind of abstract. But since you are just looking for ideas, this is just an idea which you can try to incorporate with the actual use case.
In this kind of scenario, I would first distinguish my actual data and UI state. Then I will write my component as a controlled component of actual data with the usual value and onChange props. The UI state will be kept in the internal state of the component and it will either be derived from the initial props or initialized with a default value. When the user interacts with the component, if the change affects only the internal state, we can just use setState to update the state. If it affects data also, we can fire onChange prop also accordingly. This way we can keep the actual data in the redux store, but still, keep component specific logic in the component.
As an example, let's say we want to make a text label component with in-line/in-place editing support. I would still keep the props of this component similar to the default HTML input element as value and onChange. But the flag that indicates whether to render a text or input element with 'Submit' and 'Cancel' buttons will be kept in the component as isEditMode. Initially, we can always keep isEditMode as false. But when the user clicks on the text, we change it to true, so that component will render elements for editing and hide the label. While the user changes the text we can keep that intermediate value also in UI state. But when the user clicks the 'Submit', we can fire onChange with the new value in state and change isEditMode also to false. Likewise, we can keep the component as a control component but still use the component state to manage intermediate UI states.
Hope this helps!

Should I use redux-form store instead of component state and Redux custom store?

I believe in any application there should be one source of truth.
My app will be having
90+ transaction forms and 150 reports
Complex data structures (parent level, child level, computations)
So in React I found three confusing places to store state:
Component state - use when we don't want to share data
Redux custom store (managed by developer) - use when we want to share data
Redux-form store (managed by redux-form) - use for validation
I started using redux form just for validation, and then I got confused when it allowed me to access redux-form store for data as I was already accessing data from Component state AND also from my custom store in redux
Redux form does not registers hidden fields. To register hidden fields you have to create a field with disabled attribute, etc.
If you do any computation like, AMOUNT = QTY * RATE; Here user will input QTY and RATE And AMOUNT will be computed. Here it will immediately reflect in component state, but not in redux-form state. To make it reflect in redux-form we have to fire.
this.props.dispatch(change('Invoice', 'amount', 55))
It won't be always possible to avoid component state, if I write computation formula code will look like this
Only Redux-form state
const amount = someReduxFormApiGet(QTY) + someReduxFormApiGet(RATE)
this.props.dispatch(change('Invoice', 'amount', 55))
Only react state
onChange(){ will have set QTY & RATE in component state}
const amount = this.state.QTY * this.state.RATE
Conclusion: If I go with redux-form I will have to write extra code to make redux-store stable in sync, where as state in the React component I will be having the handleChange() function that will be drawing state in this.state. Also feel I will be having lots of flexibility in component state
If my data model becomes more complex then it will be very much difficult to manage in redux-form store. Then here I am thinking to not use redux Custom store OR Component state
Other libraries that validate React inputs are not using Redux to implement validation. It's just redux-form that is using redux to manage validation.
So I reached the conclusion that
Redux-form was born just for validation and not for managing a complex data model.
Complex data models should be managed in redux custom store OR component state accordingly and not Redux-form
From the documentation of Redux-form it handles validation very well, but for data modelling purposes it is suggesting solutions that are not 100% straightforward
Need Help In Deciding
Should I use redux-form store for data modelling
OR
just use for validation
AND
use Component state & custom redux store to model data?
Thanks to erikas for the beautiful library. I have been using since it was born nearly two years ago.
I personally don't use redux-form for data manipulation. I do it by self in component state by onChange setting state. When I came to know data store in redux-form, I initially used it, but as my use cases grew, I have to shift data store to component state. Data modelling in react is something that you need to learn, it won't come by magic. But once you do it you will never get confused about Overrated state management in React
If you are performing Data modelling, dependent computations I will recommend using component state for data.
Thumb Rules:
Use only one store through the app to store state
If using Component state then don't use redux-form state (recommended)
If using redux-form state then don't use Component state (limitation - point 1,2,3 and code dirty magic behind the scene managing store)
You are right. It was born for validation, so use it for validation.
Use redux custom store as toggle, user sign-in global data flavor. But not for storing actual transactional form state (limitation -will do over coding).
If your app is going to be complex I recommend you to use
component state - actual form state with onChange
redux - use it for global in mngt(toggle,post drafts, users login info only only)
redux-from - for validation only and not as data store for submition
I also discourage you from keeping heavy, complex, state, and transactional form state in redux custom store. Just use it like ice-cream toppings.
Pros: Component state - Full control over data, flexibility what comes in what goes out, no magic behind the scenes
Cons: I didn't found any
Conclusion: redux-form is basically for very newbies to get things done quickly, but when it comes to computations, dependent fields, commercial data modelling,redux-form is not the option. But even if you do use redux-form for data manipulation soon you will be ending up with using (component state which cannot be ignored + redux-form state + redux custom state) scattered all over with confusion.
Note : I liked #vijays answer react-chopper library below , it fits all your computation requirements.Also its better than 100% better than mobx and other libraries as they dirty the code
But This react-chopper Examples is quiet empressive
It feels 100% like angular.But its uni flow from inside
Disclaimer: react-chopper is still in development And could be used for only simple to medium usecases.
I would recommend using Redux-Form only for collection and validation of data. Utilize your own component state and/or custom redux store if and when appropriate.
You're correct in only using redux for state that is to be shared. Keep things simple and reusable.
Good reading:
https://goshakkk.name/should-i-put-form-state-into-redux/
https://hackernoon.com/using-forms-in-react-redux-tips-and-tricks-48ad9c7522f6
https://medium.com/dailyjs/why-build-your-forms-with-redux-form-bcacbedc9e8
If you don't need to execute async tasks i.e async form validations then it's easy to create a custom form generator component instead of using redux-form which is much complex, adds an extra layer of boilerplate & force you to use redux.
For ref. check it.
https://github.com/bietkul/react-native-form-builder
After nearly seven frustrating months
I created a new library, React-chopper.
A revolutionary two-way binding in React that will meet any business object complexity, almost like AngularJS.
Enjoy! Code like AngularJS in React.

Resources