-
Notifications
You must be signed in to change notification settings - Fork 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
Framework: experiment with schemas to validate persisted redux data #3101
Conversation
dc0520c
to
3ff6309
Compare
412f9e8
to
b7e637c
Compare
@@ -27,15 +29,18 @@ export function items( state = {}, action ) { | |||
[ action.site.ID ]: action.site | |||
} ); | |||
case SERIALIZE: | |||
// scrub _events, _maxListeners, and other misc functions | |||
//TODO: site objects are being decorated in SitesList in lib/sites/sites-list/index.js | |||
//with either lib/site/index.js or lib/site/jetpack.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is somewhat of a tangent, but I also checked what it would take to clean up sites in the redux tree. I ran into a few issues:
- How do we cleanly pass the redux store to SitesList, where the api requests are occurring?
- We expect our in memory sites to be class instances of lib/sites/index.js or lib/site/jetpack.js. Should we move away from this pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also checked what it would take to clean up sites in the redux tree.
It would be nice if we could somehow intercept the received site prior to it being modified in the sites-list
module. Perhaps initializing the global instance early in the page lifecycle, and having the list module be aware of the Redux store, dispatching the received site upon being received? This seems admittedly awful as a long-term solution, but the long-term solution is to remove the sites-list
altogether anyways.
Otherwise, maybe we should consider performing the site object cleanup from the SITE_RECEIVE
reducer handler, so that pages/components making use of sites Redux state don't come to expect these properties and functions to continue to exist.
Should we move away from this pattern?
Yes. If context-specific behavior is desired, these could probably be reimplemented in the selectors and actions, e.g.
if ( isJetpackSite( state, siteId ) ) {
dispatch( requestAvailableJetpackUpdates( siteId ) );
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise, maybe we should consider performing the site object cleanup from the SITE_RECEIVE reducer handler
This sounds good as a first step, and move where SITE_RECEIVE is being fired for #2757 Some of the sites-list lifecycle changes might be tricky and would be better in a separate PR.
I like the choice of |
b7e637c
to
bc58d49
Compare
@aduth Thanks for the 👀 ! Great feedback. |
bc58d49
to
b0848ae
Compare
//TODO: do not pass a decorated site object to SITE_RECEIVE | ||
//site objects are being decorated in SitesList in lib/sites/sites-list/index.js | ||
//with either lib/site/index.js or lib/site/jetpack.js | ||
const blackList = [ '_headers', 'fetchingSettings', 'fetchingUsers', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how nasty would it be to use a whitelist? tends to be safer and more future proof.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping to fix this properly soon by passing the resource before it's decorated to fix #2757
tests pass, trying the code |
code works. my comments are just minor things, feel free to 🚢 |
b0848ae
to
e29ce8c
Compare
e29ce8c
to
84632cd
Compare
Framework: experiment with schemas to validate persisted redux data
The Problem
If we persist redux data, what happens when our tree changes? Our data shape is different right? Currently we do nothing, which is a little like this:
But as a dev, lets say we run master, let the redux tree persist, and then switch to a branch that has some minor refactoring for an existing subtree.
We then see something like:
Not good. A normal user can hit this case too, just by visiting our website, and the coming back 2 weeks later.
(Don't worry
persist-redux
is off in all envs!)Solution
Let's check to see if our data shapes match. If the persisted data doesn't match our schemas, we throw it out and rebuild it from scratch.
As a continuation from #2754, this is an example of how we might use schemas to validate persisted redux data.
As a recap, in each reducer,
SERIALIZE
takes what's in memory and returns a simple JS object. Similarly inDESERIALIZE
the reducer is given state that is a simple JS object. With this PR, we then validate if the data matches the shape that we expect. If it is valid, we further manipulate the JS object to match what the subtree expects in memory (this might be a no-op, or say instantiation of Immutable.js objects). If the data is invalid, we return the default initial state.There is some developer overhead for maintaining schemas, but I find that it's a great way to understand what's in the tree (without spinning up Calypso), and it gives us a lot of flexibility in refactoring our tree, since if the shape doesn't match, we rebuild it from scratch.
The following uses state/sites/items as an example using json schema v4 and tv4
Testing Instructions