Open MKwenhua opened 7 years ago
So it seems that I have sort of covered why deeply nested objects can throw but below I would like to explain each of the main reasons why this can cause problems as well as a potential remedy in case nesting is absolutely necessary.
Why Nesting Can Lead To Issues:
So lets say that each fields metadata is randomly created with different nested values. What this means is that each field cell/component when being rendered needs to consider what the object's shape is. Because of these different nested states a implicit dependency is created between how the data is stored in the database and how the data is accessed within both Rails Cells or React.
An issue that arises when data is nested is that any change or removal of a nested key runs a risk of accessing a property on a null
or undefined
property. This issue can be avoided however when using flat 1D objects because accessing a nonexistent key on an object will not throw an exception. Additionally with ESNext completely flat objects can be treated as separate objects using the rest operator:
const metadata = {
render_method: "wysiwyg",
field_id: "8a810-72726hnva-jhvjssdcs",
style: {borderRadius: "8px"},
src: 'an_image_url',
id: "blog_body_editor",
data-gtm: "7828734687346834"
}
//now just pull out the non attribute keys as such:
const { render_method, field_id, ...attrs } = metadata;
In Redux every dispatch generates and creates a new object created from state. Often times when working with nested objects, devs accidentally replace the object with just the changes. For example:
const TheState = {
connected: true,
user_profile: {
friends: 6,
name: 'Richard Feynman',
sandwich_type: 'Pastrami'
}
}
//Now within the reducer for action NEW_FRIEND_ADDED
{
. . .
case NEW_FRIEND_ADDED: {
return {
...state,
user_profile: {
friends: state.user_profile.friends + 1
}
}
}
. . .
}
This error would result in the new state being:
const TheState = {
connected: true,
user_profile: {
friends: 7
}
}
But this can be fixed by doing a spread of the rest of the object:
{
. . .
case NEW_FRIEND_ADDED: {
return {
...state,
user_profile: {
...state.user_profile,
friends: state.user_profile.friends + 1
}
}
}
. . .
}
So as you can see the deeper you nest the more unwieldily it gets.
If data is flattened abstractions below can be built to make rendering much easier. For example lets assume we have an array of field types:
Step.FormFields.map((field, i) => {
const {render_method, field_id, ...data} = field.metadata;
return FieldTypeRendMethods[field.type][render_method](data)
})
@toastercup I will add some more comments when I get home tonight, so just wait till tomorrow morning before taking me off the contributor list. I need to pack up my things
@MKwenhua take your time - I don't have to take you off contrib right away
Currently there are a few issues with how Decorator data is currently structured that make it more difficult to both render and customize.
Some of these issues are as follows:
One of the issues with data other than
id
andrender_method
is there is no standardization across different FieldTypes for attribute data. Additionally the deep nesting can cause null errors as data tried to get accesseddata[:input][:display][:styles][:height]
could easily break if any of those expected Objects are not present.Proposed Change:
Given that these elements will soon be rendered in React we can take advantage of a few ES7 features that allow encapsulation while still remaining flat. For example we could set the
metadata
to be shaped something like this:This data could then be passed into a
Field
component that can use the rest operator to bunch all data that is notid
orrender_method
into an object calledattrs
.Index
andWizard
Decorators in how their data is laid out. For example:Additionally having
cells
be an array while easier for ruby makes look up and access more complex and inefficient for tracking and updating changes to the data in React.Proposed Change:
We should make data as flat as possible and keep all data on the first level and achieve nesting via reference keys.