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

Best practices for redux-based plug-in architecture #57

Open
tnrich opened this issue Feb 9, 2016 · 5 comments
Open

Best practices for redux-based plug-in architecture #57

tnrich opened this issue Feb 9, 2016 · 5 comments

Comments

@tnrich
Copy link

tnrich commented Feb 9, 2016

Hey there,

I recently stumbled upon your work with griddle 1.0 and am very intrigued by it. I'm just wondering if the plug-in architecture you're using is based on prior work, or if it is something that you yourselves are pioneering.

Have you done a search of how other developers are building plugin-able architectures on top of redux?

I'm currently trying to create an IDE of sorts for biology, and so am looking for best practices when it comes to building a reusable, plug-in-based architecture with react+redux.

Thanks for your time,
Thomas

@ryanlanciaux
Copy link
Member

Hey there and thanks for asking!

The ideas here are based on a lot of other things but it was something we started doing without much input from other React/Redux projects. The initial idea came about before we were using Redux (at the time we were using a homegrown flux library that was using Immutable for state and a series of reducers). We were super thrilled when Redux came out since it allowed us to focus more on the grid-specific code but we kept the similar "plugin" ideas that we were originally planning on using.

While this works for our grid, it would be nice if there was something more reusable for any project using React+Redux. I have not researched this too much so this could totally exist and I may be unware 😄.

Please keep us updated if you find anything more on this!

@rafaelugolini
Copy link

+1

@tnrich
Copy link
Author

tnrich commented Feb 15, 2016

Hey there, I am trying to understand this portion of the docs:

Reducers in Griddle are methods that work against an immutable state object. A standard reducer method should look like:

export const SOME_CONSTANT_NAME(state, action, helpers) {
  return state;
}

A few questions:

  • Is this reducer function only run when the constant matches the action.type field?
  • Is each reducer passed the entire state object, and that can reducer can change any piece of the state?
  • Is this inherently different than the standard redux model, and if so, what was the rational for changing the redux paradigm in this way? Is it simply to provide flexibility?

Thanks for helping me understand your system. As I said above, it is very intriguing. I think many people will be interested in figuring out a set of best-practices for designing plug-in architectures based on react+redux.

@ryanlanciaux
Copy link
Member

Thanks for asking - we definitely can improve that part of the documentation to be clearer.

  • The reducer is only called for that specific name OR the _BEFORE / _AFTER, etc. reducers (more on those in the architecture docs but basically the flow is like
GRIDDLE_LOADED_DATA [from griddle]
|> GRIDDLE_LOADED_DATA_AFTER [from plugin1]
|> GRIDDLE_LOADED_DATA_AFTER [from plugin2]

The output from the reducers gets passed into the connector which becomes the props on the Griddle view components. As a side note, I'm also exploring using reselect in the reducers to help slim down what data gets passed through the connector.

  • Griddle + Plugins share one immutable state object and each reducer can return an entirely new immutable state object if desired. Generally the reducers are just interacting with small parts of the state object but theoretically could be something where every property is different (it's an immutable object so it's "different" in each reducer that modifies the state object as it is but I mean each node in the state tree could be different).
  • This is somewhat similar to standard redux pattern with the exception of the following:
    • Each grid is treated as it's own app. Every instance of Griddle is connected to it's own store (with the default core/connector/render configuration). We wanted to make it so that you didn't have to be using Redux in your host application to use Griddle. We would love to make it so that if your host app is also using redux you can attach to the store the rest of your app is using. Currently Griddle doesn't fully embrace the The whole state of your app is stored in an object tree inside a single store. -- You can use data from your app's store but Griddle maintains it's own store as well for it's local, grid state.
    • _BEFORE/_AFTER filters discussed above and the "helpers" parameter. I have some heartburn with the existence of the "helpers" parameter and am considering instead making them utility libraries that each module / plugin imports as needed so we could share the standard state, action parameters for each reducer. The helpers parameter is kind of an artifact of the earlier reducer design before redux. That said, it's really handy to be able to overwrite helpers in a plugin to avoid the need to totally override a reducer (aka if you know a reducer is performing 5 operations and you only need one thing to be different -- a helper is how that is achieved currently). I am interested to discover if that will make maintenance over time difficult with the helpers potentially being an unknown.

Please let me know if that helps clear anything up or any ideas you may have around that. I would love to see a more widely embraced pattern emerge (and again it's totally possible there is something out there I'm missing that would serve these same needs 😄) 👍

@ryanlanciaux
Copy link
Member

Wanted to note this here -- we're currently in the process of removing helpers in favor of selectors. (See this branch).

As noted above, helpers were an artifact of an earlier architecture and selectors should mostly accomplish everything we were using them for (with the added performance boost given by reselect's default memoization). Additionally, pushing most of the logic to the selectors is allowing us to simplify our reducers quite a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants