-
-
Notifications
You must be signed in to change notification settings - Fork 15.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to update nested props in reducer? #432
Comments
With: {
...state,
myPosts: {
isPending: true
}
} you are replacing whole const initialState = {
myPosts: {
isPending: false,
data: []
}
}; For example you can manually merge deep object properties like this: {
...state,
myPosts: {
...state.myPosts,
isPending: true
}
} |
Thanks for answers. As for me the last variant is the cleanest. {
...state,
myPosts: {
...state.myPosts,
isPending: true
}
} |
Is this actually how people do this? My reducers are getting very, very lengthy going multiple levels deep. |
@matisoffn : that's one of the reasons why you are encouraged to keep your Redux state as flat as possible. Writing "manual" nested update code gets really ugly. FYI, I have a work-in-progress set of new pages for the Redux docs on "Structuring Reducers", and the page on Immutable Update Patterns discusses this a bit. Overall, the basic approaches to avoid nested object updates are:
As a general FYI, the issue discussing the new pages is at #1784 , and the main WIP page is at https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md . |
Thanks so much @markerikson |
First, it looks like you're using TypeScript. TypeScript is going to behave differently than "normal" Javascript. Second, while the Array Spread operator is part of ES6, the Object Spread operator is still a Stage 3 proposal, and is not yet a final part of the language. The syntax can be enabled if you're using Babel by adding the appropriate compiler plugin. For TypeScript, I think that was just added in TypeScript 2.1. |
use babel object spread operator and .babelrc file |
@mohak1990 Can you use babel and TypeScript together? |
@HomeboxJim Yes, you can. Alhough I don't have time to locate a reference, I'm using it currently in multiple projects. In one, TypeScript compiled to a "JS output" folder, and then babel sees the changes there and then compiles it further using babel. In another, TypeScript and Babel are both applied as webpack loaders (
|
To go even deeper you can do the following:
|
Going along with this, how would I update a nested dynamic key? For instance, if I have the following: ...
data: {
key1: {
key: 'key1',
name: 'key1'
},
key2: {
key: 'key2',
name: 'key2'
}
} I then perform some update on a key and then have an action coming in with the new key like the following: In my reducer: return Object.assign({}, state, {
...state,
data: {
...state.data,
/* how do I dynamically set the key here to change key2 based on the action? */
needsToBeDynamicKeyHere: action.data.key
}
}) In my use case, I am dynamically mapping a location to a particular category which is already in the state. (For instance, key2 could be the category that my logic decides to map the location to). Then, I make updates to that particular category. After that, I need to save the category back into the state. However, I don't want to statically type out each category (there are several). I basically need to be able to in the action specify which category to update (e.g. |
@ntomallen : use an ES6 computed property: return {
[someVariableOrExpression] : someValue
}; so in your case: return {
...state,
data : {
...state.data,
[action.data.key.key] : action.data.key
}
} |
Is there any way to do state drilling better? setIn from Immutable.js seems to do the trick but wouldn't like to import the whole library only for this: const { Map } = require('[email protected]')
const originalMap = Map({
subObject: Map({
subKey: 'subvalue',
subSubObject: Map({
subSubKey: 'subSubValue'
})
})
})
const newMap = originalMap.setIn(['subObject', 'subKey'], 'ha ha!')
// Map {
// "subObject": Map {
// "subKey": "ha ha!",
// "subSubObject": Map { "subSubKey": "subSubValue" }
// }
// } |
@franciscop-invast : there's dozens of immutable update utility libraries available. I personally would suggest using Immer, as it's the simplest to use. |
There's also updeep (https://github.com/substantial/updeep), which is the
library I use.
|
If your state object is a dictionary where the keys are variable Ids instead of known words, you can do this:
|
Ha-dooooo-ken!!!
...just to update a simple date for a contract... |
@sandrumirceaioan note today we specifically recommend using Immer, which is already built into our official Redux Toolkit package:
and using Immer would drastically simplify that code |
I can't figure out the correct way to update nested property in reducers state. When I write return in such was the "data" property is not merged. Or maybe I shouldn't use nested properties in reducers at all?
The result is
The text was updated successfully, but these errors were encountered: