Should stores call actions in reactjs flux? - reactjs

My current reactjs/flux implementation is to have components call actions, and actions call the web api which then funnels back to the store.
I have a set of checkboxes where the state of the checkboxes are managed in a store, but every time I update the checkboxes, I would like to make a query to the server with the state of the store. What I am forced to do now is call an action to update checkboxes store when the checkboxes are clicked, in the checkboxes store, set a variable to "queryServer", then in the checkboxes component, check the "queryServer" and make another action to query the server.
It seems simpler if both components and stores can make action calls, that way, when I update the checkboxes store, I can initiate the action to query the server directly without setting a silly "queryServer" variable and having the component check that.
Though it does seem to make things simpler, it seems to go agains the essence of the flux architecture where all actions are initiated from the view.

My approach would be to fetch the state of the store into the view and pass it to an action from there. This would allow your store to stay as dumb as possible, simply receiving data as it comes into the application.
In more specific terms, your store would have a getData function that returns the raw data stored. In your component the click handler for your checkboxes would include code looking something like this:
var data = MyStore.getData();
MyActions.queryServer(data);
Your action would then make the API call (since it's probably the safest place to do anything asynchronous) and pass the new data to your store via the dispatcher.

Related

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.

Redux Form - multiple update function renders slow

I am using redux-form 7.2.0.
In my Project , I have 30 Fields in my form.
Based on the First Field Value , i need to update some 20 fields. i call change action creator for 20 times. it takes more time to render these 20 fields. very slow.
is there any way to make it fast in render?
or
is there any way to update multiple fields in single action?
please help me to rectify this
Really the only correct answer is to use an additional middleware provider. See dispatch multiple actions from Redux action creators to get an idea of the pros and cons.
You could set a flag somewhere in your state tree when the first field changes, avoid rendering via shouldComponentUpdate until all fields have been updated, then when everything has been updated, set that flag back.
The only other way I could think about handling this would be using the reducer.plugin to make a larger state change, but I think this is a dangerous path that could easily break in the future and just not behave in a predictable manner.
Currently batch field changing is not supported by redux-form or redux directly.
Just use initialize action provided by redux form.
There are two ways to use this:
https://redux-form.com/7.4.2/examples/initializefromstate/ Initialize it when creating a form, like they did in the example.
Pass 'initialize' action as prop and call to update all the fields with one action call.
const data = { firstName: 'John', lastName: 'Doe'};
this.props.initialize(data);
Just make sure to match the field names with keys in data object.
This will fire one action and all fields will be initialized.

Angular Forms with Redux

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.)

Setting a flag in component state directly without getting into a full Flux cycle

I started with FLUX very recently, and need some advise on how should I update the component state and the store.
I need to set a toggle flag which is bonded to an onclick event, from what I understand in Flux architecture, I should call an action then trigger a dispatch event and then the store will update and emit update resulting my component to receive the update and re-render. (Please correct me if I'm wrong here)
Component Code look like this:
...
_updateState:function(){
this.setState({myTrigger: MyStore.myTrigger});
},
_onClickEvent: function(boolValue){
MyActions.updateTrigger(boolValue);
},
...
render: function(){
return: (
...<div onClick={this._onClickEvent}/>...
)
}
...
I wonder why shouldn't I just call setState directly which would trigger the re-render directly and avoid going through the full flux cycle which I don't really need since I will always pass in "true" for this function, which really is the same as not passing any data over to the store.
Code will look like this:
...
_onClickEvent: function(){
this.setState({myTrigger: true});
}
...
Seemly to me this is by-passing the flux single directly process flow concept and creating a component event loop within the component. Is this wrong to do? Can anyone help me understand the reasoning behind why this is a good or bad practice to do so?
Thank you very much!
DD
This is not wrong. The Flux data flow is intended to handle data which are either persisted or shared between components. If the data is only used in this component and there is no persisting of the data, the last example you show is the correct way. There is no need to overcomplicate things, that is not why Flux is there.
Flux gives you the uni-directional data flow architecture. This means that if your application wants to share or store data, then you want to use the Flux architecture. This way you can fetch or post data and then notify your components when the new data has arrived.
An example would be in a message system. You want to fetch a message.
First you trigger an action with MyAction.fetchMessage(message);
Then you do a get request to whatever application that stores your messages. When that returns you send the data to your MessageStorewhere you cache your data. After that you trigger an event from the store which tells the components that the new message has arrived. From there on the components just fetched the new message from the store and re-render.
That is when the Flux architecture is brilliant. It is easy to see the data flow through your system, which makes it easier to debug and easier to keep data separated from the components.

In Flux what's the appropriate way for an action in one React component to affect another component?

I'm trying to wrap my head around Facebook's Flux...
Say I have an app with a side menu that can be hidden and shown via a button in the header.
My header is one component, my side menu is another component.
Currently my Header component just sets a class on the HTML div side menu element which gets animated to hidden by CSS.
What's the general idea here?
ReactJs doesn't really care about how it gets its data (how it's data is getting passed in or how that data should be handled across the web application). That's where Flux comes in, it creates a functional approach on how data is handled. Data-flow is essentially:
Action -> Data Store -> Component
Mutation of data happen through calling Actions. The Data Stores themselves have to listen on the actions and mutate the data within the store. This keeps the data structure and logic flat.
In your case, your dataflow would probably look something like this:
Header --> User Click --> Fires action --> Updates store --> Side menu listening and responding to that store change.
Your case is a simple example which you probably don't really need Flux. I think it's easier if you have a parent component that maintains the view state logic, and use props/callbacks for the 2 children components (side menu and header). But a more advanced example that you need to make ajax calls and maintain session, Flux would become useful. Like if you have a Login Component, and you want to show different side-menu options and header options depending on user:
Login Component --> User Logins --> Calls Action #signIn --> Showing Loading State
--> Dispatcher handles action (make api call to authenticate user and load user data)
On success (for the api call), alert sessionStore, and populate store with data
On error, maybe fire another action that says login failed or something
SessionStore ---> Header Component (Listens to Store) --> Update view based on store information
---> Side Menu Component (Listens to Store) --> Update
speaking more general:
flux is a software architecture for a unidirectional Dataflow. It's Chain is Action -> Delegation -> Store -> View... The action - for example a Button Click - gets delegated to stores where your applicationlogic and data is kept... here your action and data will be changed and processed. The store eventually emits an event which views (for example react components) previously registered on with a callback. In this callback you can GET your data from your stores. It is important to mention that you can only access the stores READ-Only.
So for your case... if you want component A to affect component B you will have to register component B to the store eventEmitter and GET the desired data from the store. Once component a triggers an action it gets delegated to the store, your functions are performed and eventually the event gets thrown that starts component B's callback.
Hope this got clear enough... its way cooler with some nice drawings.

Resources