The thing that has puzzled me the most ever since I started reading about SPAs is how to handle the application state.
Although I have found in Redux most of the answers I was looking for there's still a couple of things that I'm not sure how to handle.
One of those things is how to specify the shape of the "entities" I want to use in my app. In other frameworks I've used in the past I've seen an extensive use of ES2015 classes for this purpose, but in React/Redux applications object literals are by far,the preferred way to express the application state. Last night I was reading about normalizing data in the redux docs, and although it gave me great ideas about how to deal with deeply nested objects, it left me with the feeling that there was something missing and that thing is how to specify in a single spot and as clear as possible what the structure/shape of the state of the application is.
Take the sample data used in the article mentioned above:
{
posts : {
byId : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
}
allIds : ["post1", "post2"]
},
comments : {
byId : {
"comment1" : {
id : "comment1",
author : "user2",
comment : ".....",
},
"comment2" : {
id : "comment2",
author : "user3",
comment : ".....",
},
"comment3" : {
id : "comment3",
author : "user3",
comment : ".....",
},
"comment4" : {
id : "comment4",
author : "user1",
comment : ".....",
},
"comment5" : {
id : "comment5",
author : "user3",
comment : ".....",
},
},
allIds : ["comment1", "comment2", "comment3", "commment4", "comment5"]
},
users : {
byId : {
"user1" : {
username : "user1",
name : "User 1",
}
"user2" : {
username : "user2",
name : "User 2",
}
"user3" : {
username : "user3",
name : "User 3",
}
},
allIds : ["user1", "user2", "user3"]
}
}
How would you express the shape of this data? Just like this?
{
posts : {
},
comments : {
},
users : {
}
}
Or perhaps:
{
posts : {
byId : {
}
allIds : []
},
comments : {
byId : {
}
allIds : []
},
users : {
byId : {
}
allIds : []
}
}
Well, that tells me nothing about the actual shape of the objects that live inside each of the byId
objects and that's exactly what has been bothering me since I started studying a little bit of Redux.
So the question is, is there any way/common practice that would let me express in the clearest possible way, the shape, specifically each of the properties of the objects that make up the state that the store is going to manage?
As author of that "Structuring Reducers" docs section, that's because the actual content of your data items is entirely dependent on you and your application. This is really more of a generic Javascript "how do I express types?" question. There's static type systems like TypeScript and Flow; documentation-based approaches like JSDoc; runtime approaches like the React PropTypes library or tcomb; and schema-based approaches like JSON-Schema. Any of those approaches are valid ways to document and enforce data type definitions within an application.
Normalization is simply an approach for organizing those values, regardless of how you've chosen to define what their contents are.
Assuming you're using plain JS, the simplest way is to use propTypes.shape.
// An object taking on a particular shape
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
If you're using propTypes, I suggest declaring the shape of all objects in this manner.
Benefits:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With