Skip to content
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

Themes: Switch data fetching to Redux #840

Merged
merged 12 commits into from
Dec 16, 2015
Merged

Conversation

ockham
Copy link
Contributor

@ockham ockham commented Nov 26, 2015

Notes by @mcsf:

Context

What started as an experimental branch for a number of Redux-related changes across Themes coalesced into a substantial refactor of our data fetching components, which are now Redux-connected. This means that this PR moves Themes entirely to Redux.

Decisions

  • ThemesListFetcher, ActivatingTheme, and CurrentTheme (i.e. the data component) are kept as generic data components that relay application state to their children.
  • Selectors are given much greater importance, as they allow us to simplify the data model by avoiding forms of data duplication — notably, avoiding storage of derived data next to essential data.
  • Use of selectors allowed to altogether eliminate one action: SEARCH_THEMES, which was basically a virtual action (read: hack) to trigger client-side filtering of themes, a feature specific to Jetpack sites.

Next

  • Stores, and helper functions in reducers are now obsolete, and are removed in Themes: Remove Flux stores #1363 to keep this PR's size down.
  • We need to move files to different locations in order to comply with Framework: Introduce top-level Redux state directory with sites example #751. This PR is big enough already, so that will be done separately.
  • As we progress, more derived data should be able to be eliminated from the global state's themes branch.
  • Some features of the Showcase invoke non-Themes action creators (namely, purchases and customization). This PR uses the dispatch() function from context.reduxStore in the relevant sections to dispatch the corresponding Redux actions. Another possible approach would have been to have a layer of Redux middleware that dispatches certain actions to the singleton Flux architecture.
  • Memoization of selectors is something very useful to have, and trivial to implement thanks to immutability. However, there are server-side-rendering-specific concerns; specifically:
    • To avoid user-specific data leakage between Node requests, most memoized selectors would have to be bound to a particular request and be GC'd afterwards. This would work the same way that our global Redux store on the server is always bound to a request.
    • For performance improvements, it could be very advantageous that some non-user-specific selectors were capable of cross-request memoization, though care should be given to ensure said selectors's memory usage doesn't grow unintentionally.

Bugs

  • Jetpack sites: searching refetches the themes list when it doesn't need to, though this only happens for the first search.
  • Jetpack sites: searching blurs the search field.

Testing

QA should focus around navigation of the Showcase, switching between sites, including both WP.com and Jetpack sites, searching, per-tier filtering, triggering InfiniteList's fetching, and switching between Showcase and other sections.

@ockham ockham assigned ockham and mcsf and unassigned ockham Nov 26, 2015
@mcsf mcsf added this to the Themes: Showcase M3-LoggedOut milestone Nov 26, 2015
@ockham
Copy link
Contributor Author

ockham commented Nov 26, 2015

Just tried to stick this into #846, to provide data to the themes list we render there, server-side. This could work okayish, but ideally, I think we should use the Redux-based themes-list-fetcher on the client side too, in order not to duplicate code. So maybe that could be the goal of this PR?

@ockham
Copy link
Contributor Author

ockham commented Nov 26, 2015

@ehg @seear Join the party :-)

@mcsf
Copy link
Member

mcsf commented Nov 26, 2015

I think we should use the Redux-based themes-list-fetcher on the client side too, in order not to duplicate code. So maybe that could be the goal of this PR?

Yeah, that's where I'm thinking of heading!

@mcsf
Copy link
Member

mcsf commented Nov 26, 2015

#338 opened a nice precedent for client-side usage of a Redux global store, so… seems like the pieces are falling together, we can work with that momentum.

@ehg
Copy link
Member

ehg commented Dec 1, 2015

I noticed that search/tier selection was funky, 0aca329 is a possible fix :P

@mcsf
Copy link
Member

mcsf commented Dec 1, 2015

I meant to fix it, thanks for taking care of it :).

// console.log( 'Flux -> Redux' );
// reduxStore.dispatch( action );
// } );
//}() );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Did this work? :)

I'm thinking we probably don't need to integrate the two dispatchers now, as the Redux transition is getting some momentum behind it. We should check we're not relying on any 'external' actions, although from what I can remember, we're not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Did this work? :)

It did. :)

we probably don't need to integrate the two dispatchers now

I agree. I pushed it for the sake of communicating the exploration process, i.e. as a way of saying that this in particular had been tried.

We should check we're not relying on any 'external' actions, although from what I can remember, we're not.

Yeah, IIRC only the reverse happens, and that's something we can handle at the Redux middleware level.

@ehg ehg force-pushed the try/themes-redux-transition branch from 0aca329 to a793461 Compare December 2, 2015 10:46
if ( page > 1 && ! loading && lastPage ) {
this.onLastPage && this.onLastPage();
}
fetchNextPage( site );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got kind of confused between the AC fetchNextPage and the fetcher's fetchNextPage function. Perhaps namespace/rename?

@ehg
Copy link
Member

ehg commented Dec 2, 2015

This is looking great. I removed some dead code, and rebased.

The Jetpack search is quite amusing atm ;)

@mcsf mcsf force-pushed the try/themes-redux-transition branch from 578e4c6 to 5d45aab Compare December 3, 2015 01:23
@mcsf
Copy link
Member

mcsf commented Dec 3, 2015

Thanks for your feedback and fixes. I just pushed substantial changes that should make this PR a lot simpler and ship-worthy. Subsequent feedback and some testing would be greatly appreciated. :)

The Jetpack search is quite amusing atm ;)

Heh, indeed. Hopefully, it's looking better now.

@mcsf
Copy link
Member

mcsf commented Dec 3, 2015

On derived data and selectors: the changes brought around searchJetpackThemes/getFilteredThemes are a good illustration of what I've said in the past about Redux allowing us to significantly trim the themes branch of the global state.

Our data needs for themes are likely too simple to justify the 4 subreducers we have for it. Improving that isn't the goal of this PR, but it's something to be aware of.

@ehg
Copy link
Member

ehg commented Dec 3, 2015

the changes brought around searchJetpackThemes/getFilteredThemes are a good illustration of what I've said in the past about Redux allowing us to significantly trim the themes branch of the global state

Wow, yes. This looks much nicer. Perhaps update the PR description with what you guys have done, and how it's better? I figure this would be a good example to give to others, on how to reduxify.

@mcsf mcsf changed the title Themes: Try a pure Redux render tree Themes: Switch data fetching to Redux Dec 3, 2015
@mcsf mcsf added the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Dec 3, 2015
@mcsf
Copy link
Member

mcsf commented Dec 3, 2015

Perhaps update the PR description with what you guys have done, and how it's better? I figure this would be a good example to give to others, on how to reduxify.

Indeed. I've rewritten the PR description and added the NR label.

@ockham
Copy link
Contributor Author

ockham commented Dec 3, 2015

Quick note from testing -- purchasing a theme in single-site mode doesn't seem to update the CurrentTheme component.

@ockham
Copy link
Contributor Author

ockham commented Dec 3, 2015

How well do our flux-actions (that use my combineStores() helper at an intermediate step -- and hence Flux stores created from reducers via lib/store's createReducerStore()) work with the global Redux store (created from Redux's own createStore())? Do we have to remove them, and use our Redux actions directly everywhere?

)
// TODO: Remove function when using React 0.14
React.createElement( ReduxProvider, { store: context.reduxStore }, () => {
return React.createElement( ThemesComponent, {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we shorten () => { return x; } to () => x ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely.

@mcsf
Copy link
Member

mcsf commented Dec 15, 2015

Pushed a commit to change them to // Connected props, which I'd deem fairly informal -- no need to look up the exact wording for future devs as it'd be okay to put in something equivalent, such as // connect() or whatever.

Doing pseudo-JSDoc -- introducing statements that don't exist, and would break JSDoc if we were ever going to use it -- was on second glance just so much against my OCD >:|

👍

@seear
Copy link
Contributor

seear commented Dec 15, 2015

I've tested around preview->customize->activate and the Tracks events. Looking good with no apparent regressions. Noting that we don't have a working Tracks event for jetpack search, with or without this PR.

@mcsf
Copy link
Member

mcsf commented Dec 16, 2015

:shipit:

Substantial refactor of our data fetching components, which are now Redux-`connect`ed.

- `ThemesListFetcher`, `ActivatingTheme`, and `CurrentTheme` (i.e. the data
  component) are kept as generic data components that relay application state to
  their children.
- Selectors are given much greater importance, as they allow us to simplify the
  data model by avoiding forms of data duplication — notably, avoiding storage
  of derived data next to essential data.
- Use of selectors allowed to altogether eliminate one action: `SEARCH_THEMES`,
  which was basically a _virtual_ action (read: _hack_) to trigger client-side
  filtering of themes, a feature specific to Jetpack sites.

An @mcsf and @ockham project, with fixes by @ehgy :-)
This way, we can avoid at least passing `getState()` as a prop to themes-selection.
@ehg ehg force-pushed the try/themes-redux-transition branch from 523337a to a84cc81 Compare December 16, 2015 16:06
mcsf added a commit that referenced this pull request Dec 16, 2015
@mcsf mcsf merged commit 79f41f4 into master Dec 16, 2015
@scruffian scruffian removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Dec 16, 2015
@ehg ehg deleted the try/themes-redux-transition branch December 16, 2015 16:15
analytics.tracks.recordEvent( 'calypso_themeshowcase_theme_click', {
search_term: queryParams.search,
theme: theme.id,
results_rank: resultsRank + 1,
results: ThemesListStore.get(),
results: themesList,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting here that ThemesListStore.get() should have actually read ThemesListStore.getThemesList() -- we had overlooked to change get() to getThemesList() when we started using createReducerStore() to create our stores from reducers. That latter function however returns objects whose .get() method returns the entire store state. Thus, we were erroneously setting results to the contents of the entire ThemesListStore state instead (including query params and whatnot) instead of just the themes list. This has been fixed by this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature Group] Appearance & Themes Features related to the appearance of sites. Server Side Rendering
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants