Dispatching several actions in sequence for single reducer doesn't reflect changes in state for connected component - redux

When dispatching several different actions for one reducer, only the last one triggers component update. It might be better to show then explain.
Some notes on provided example:
App component reflects a history of updates of it's prop redirectPath. When it comes as null then no redirect string adds to history.
There is a reducer which returns just a plain string or null depending on action.
By pressing a button Do redirect I expect both actions (SET_REDIRECT and CLEAR_REDIRECT) provide changed state to AppContainer component. But only the latest one (CLEAR_REDIRECT) triggers render method with null value.
If we add slight delay between dispatching these actions, then both of them trigger component's render. You can check it by pressing Do redirect with delay button.
I expect both changes (provided by SET_REDIRECT and CLEAR_REDIRECT actions) in state should trigger component update without using setTimeout when dispatching actions.
I also tried to move dispatching of CLEAR_REDIRECT from middleware, after it gets SET_REDIRECT, but the same result.
Can I somehow reach expected behaviour?
Initially I posted the issues to redux repo, because I thought it's an issue in redux, but #jimbolla explained me that it's mostly by design of react.
Here is the reference to the original issues and comments from redux team member https://github.com/reactjs/redux/issues/2532.

Don't ever rely on performing state updates in render(). The only code that should be executed in render() is the code required to construct the view.
You could use componentWillReceiveProps to track when your component receives new properties.
You should listen for the appropriate property and perform your redirect when received. You should then listened for a property that indicates the redirection was successful and then you can dispatch an action to clear the redirect state if required which will trigger another component update.

Related

Saving and applying states with NGRX

So I am learning NGRX and I am close to understanding how it works, I am dispatching events and I can see them in store-devtools chrome extension.
What I want to know is how can I save a state and apply it after? My purpose is to save a state from a specific page so that when I'm back to that page I will apply the old state and I will not lose my work there
Here's my repo: https://bitbucket.org/wmoreiradev/ngrxonfire/src/effects-refactor/
You can do this like bellow
Create actions to save and load current state.
Save the current state before leaving the page. You can do this inside the reducer function or inside a effect like bellow
localStorage.setItem("currentState", JSON.strigify(state));
When you load the page dispatch an action to load the saved state inside a reducer
case Actions.LOAD_SAVED_STATE:
return {...state, ...action.payload};
also, remove the save state from localStorage.

Should actions only be used when updating state?

Reducers listen for actions of a certain type and then update the store as needed, but should you use an action without changing the store?
Maybe on route changes or on button clicks so that what the user does shows up in timemachine, or is this abusing actions?
Actions are linked to reducers through their 'type', in general actions should be linked with at least one reducer.
It seems like you can achieve the functionality you are looking for by creating a function inside your component that is your method called by the onClick, submit, or whatever activity happens, something like this:
myOnCLickMethod(passedInfo){
const {dispatch} = this.props
//any JavaScript code you need
dispatch(myAction(passedInfo))
}
This ensures you can do anything you want that doesn't touch the state while still allowing for actions to fire and state changes when that activity happens.
An action is a call for state change. So if route changes or button clicks don't change the state of your app, you shouldn't use actions for them. Maybe log is more relevant in this scenario.

How can we update the fields of a redux form by dispatching an action

i have two fields with redux form. I have a refresh button through which i update my state through an action. This refresh button updates three text values. My problem is that i must refresh the field values of my form. How to update the state of my redux form. I'm thinking of using a selector like this:
export const formsState = state => state.get('form');
Then i will create a reducer which is taking the formstate and updates it with
update formsState
.update('order', action.payload.price);
But i dont think this is the best solution. Do have some better ideas?
Make sure you refresh button send an action which will update your store via the reducer.
In order to update your component I would suggest to use a react containers usinng connect.
Use the following function:
store.getState() to get your state.
store.dispatch() to dispatch your action.

How does redux keep independent state for the same component of many page when routing?

When I use Redux with react-router, I have the same component 'ticker' on pageA and pageB, when I dispatch action to 'ticker' on pageA and then route to pageB, 'ticker' on pageB is pageA's 'ticker's' state.
How can I split the component state?
And if has a easy way to set all the state to default state when routing ?
Sometimes it's a good idea to store component-specific state inside React's component state. In your case, if you want the state for each component to be reinitialized every time it is remounted, then it's better to update the state using React's setState.
Redux creator's opinion on this matter: https://github.com/reactjs/redux/issues/1287#issuecomment-175351978
On the other hand, if you want pageA's component state to be preserved between route transitions, then I'd imagine you'll have to assign some sort of ID to pageA's , and use that to store the corresponding state data in the redux store.

Angular2 Change Detection with Zones

I am wondering if all asynchronous events and callbacks can be traced back to a specific source component by wrapping all component logic (including logic of non-component directives inside component) in a zone, then only that source component needs to be checked for changes along with any child components with changed inputs from the source component, assuming all changes are following the uni-directional flow.
Is this understanding sound?
Is this change detection strategy available in Angular2?
Why is Angular2 detecting changes on all the components after any asynchronous (XHR) event?
One whole Angular application runs in a single zone. Angular uses the zone to patch async APIs and uses notifications from these patched APIs to run change detection every time some async event happened.
The uni-directional flow is for [prop]="value" bindings that works only from parent to child.
Angular runs change detection from root to leafs.
If ChangeDetectionStrategy.OnPush is configured for a component, change detection skips these components (and their descendants) until some binding (inputs) have changed.
There are other strategies to optimize CD.
For example observables and promises, that actively notify about changes and don't need change detection.
Immutable objects which are guaranteed to not change their propery values.
Update
Angular doesn't know what values an event handler has changed. Properties of a component, of a global service, of object references that were passed around, .... It just assumes that when an event handler was called that probably something has changed and then runs a complete change detection cycle to propagate all bindings from parent to child.
Child do parent bindings are events anyway and therefore aren't updated during change detection.
... by wrapping all component logic (including logic of non-component directives inside component) in a zone, then only that source component needs to be checked for changes along with any child components with changed inputs from the source component, assuming all changes are following the uni-directional flow. Is this understanding sound?
When an template-bound event fires – e.g., (click)="doSomething()" – the doSomething() method is free to alter any component or application data. Template statements, such as our doSomething() event handler, are not bound by the unidirectional flow rule, as per the Angular docs:
Responding to events is the other side of Angular's "unidirectional data flow". We're free to change anything, anywhere, during this turn of the event loop.
This is why, by default, Angular's change detection has to check every template binding in every component after an event fires. (Well, after an event within the Angular zone fires.) Angular doesn't know what might have changed... it has to discover what has changed.
The unidirectional flow rule applies to template expressions such as {{some expression}} or [childInputProperty]="parent expression" or if you implement an input property setter method: #Input() set childInputProperty(variableName:type) { ... }.
Is this change detection strategy available in Angular2?
No, because it would severely limit what an event handler could do. Dirty-checking every template binding may not be the most efficient way to detect changes, but it makes it much easier for us to write our event handlers (i.e., to write our applications).
Why is Angular2 detecting changes on all the components after any asynchronous (XHR) event?
Angular doesn't want to limit what we can do in our event handlers. An event handler bound in ComponentA's template can change data that is local to ComponentA, but it can also change data that is in a service (and hence it can change data that is visible to other components), and it can change data in other components, e.g., by calling public APIs/methods on other components.

Resources