Redux & NuclearJS #216

Closed
neverfox opened this Issue Jul 5, 2015 · 7 comments

Comments

3 participants
@neverfox

neverfox commented Jul 5, 2015

Both of these projects seems to have a lot of similarities both in philosophy/implementation and mutual respect for one another (one could even see these projects merging one day?). Since I'm "in the market" for a functional, reactive Flux implementation, what would be the things to consider between the two? What would you say are the advantages of Redux over NuclearJS?

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jul 6, 2015

Collaborator

Here's why I chose to write Redux instead of using NuclearJS:

  • I don't want a hard dependency on ImmutableJS
  • I want as little API as possible
  • I want to make it easy to jump off Redux when something better comes around

With Redux, I can use plain objects, arrays and whatnot for the state.

I tried hard to avoid APIs like createStore because they bind you to a particular implementation. Instead, for each entity (Reducer, Action Creator) I tried to find the minimal way to expose it without having any dependency on Redux whatsoever. The only code importing Redux and actually depending hard on it will be in your root component and the components that subscribe to it.

NuclearJS has a really nice concept of getters but I also felt that it tries to be “too smart” around performance and I didn't want to make this mandatory. Instead, with Redux, you can achieve similar results by using a library like reselect:

import React from 'react';
import { createSelector } from 'reselect';
import { connect } from 'redux/react';

const subtotalSelector = createSelector(
  [state => state.shop.items],
  items => items.reduce((acc, item) => acc + item.value, 0)
);

const taxSelector = createSelector(
  [subtotalSelector, state => state.shop.taxPercent],
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
);

const totalSelector = createSelector(
  [subtotalSelector, taxSelector],
  (subtotal, tax) => { return {total: subtotal + tax}}
);

@connect(totalSelector)
class Total extends React.Component {
  render() {
    return <div>{this.props.total}</div>
  }
}

export default Total;

That said, NuclearJS definitely was a big inspiration to me.

Collaborator

gaearon commented Jul 6, 2015

Here's why I chose to write Redux instead of using NuclearJS:

  • I don't want a hard dependency on ImmutableJS
  • I want as little API as possible
  • I want to make it easy to jump off Redux when something better comes around

With Redux, I can use plain objects, arrays and whatnot for the state.

I tried hard to avoid APIs like createStore because they bind you to a particular implementation. Instead, for each entity (Reducer, Action Creator) I tried to find the minimal way to expose it without having any dependency on Redux whatsoever. The only code importing Redux and actually depending hard on it will be in your root component and the components that subscribe to it.

NuclearJS has a really nice concept of getters but I also felt that it tries to be “too smart” around performance and I didn't want to make this mandatory. Instead, with Redux, you can achieve similar results by using a library like reselect:

import React from 'react';
import { createSelector } from 'reselect';
import { connect } from 'redux/react';

const subtotalSelector = createSelector(
  [state => state.shop.items],
  items => items.reduce((acc, item) => acc + item.value, 0)
);

const taxSelector = createSelector(
  [subtotalSelector, state => state.shop.taxPercent],
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
);

const totalSelector = createSelector(
  [subtotalSelector, taxSelector],
  (subtotal, tax) => { return {total: subtotal + tax}}
);

@connect(totalSelector)
class Total extends React.Component {
  render() {
    return <div>{this.props.total}</div>
  }
}

export default Total;

That said, NuclearJS definitely was a big inspiration to me.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jul 6, 2015

Collaborator

Oh, and of course I had these two other goals in mind that NuclearJS did not satisfy:

  • Everything must be hot reloadable
  • It should be possible to build time travel tools with reevaluation on reload, like in my talk
Collaborator

gaearon commented Jul 6, 2015

Oh, and of course I had these two other goals in mind that NuclearJS did not satisfy:

  • Everything must be hot reloadable
  • It should be possible to build time travel tools with reevaluation on reload, like in my talk
@neverfox

This comment has been minimized.

Show comment
Hide comment
@neverfox

neverfox Jul 6, 2015

Thanks for the thorough answer. I've been studying Nuclear's React mixin to understand how I can integrate it into a not-React view layer (in my case, Aurelia). I've also started to take a look at the Collector and CollectorDecorator, but I'm having a time distilling out what's essential. Is there any good documentation or an example about generic view layer integration?

BTW, if I get this figured out, I'd be happy to share the approach for your documentation.

neverfox commented Jul 6, 2015

Thanks for the thorough answer. I've been studying Nuclear's React mixin to understand how I can integrate it into a not-React view layer (in my case, Aurelia). I've also started to take a look at the Collector and CollectorDecorator, but I'm having a time distilling out what's essential. Is there any good documentation or an example about generic view layer integration?

BTW, if I get this figured out, I'd be happy to share the approach for your documentation.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jul 6, 2015

Collaborator

Basically Redux's top-level API is just { subscribe(listener), dispatch(action), getState() }.

Provider makes it available down the React component tree via context. Connector uses subscribe(listener) to listen to changes and read from getState() when a change occurs.

These are the only essential parts.

Collaborator

gaearon commented Jul 6, 2015

Basically Redux's top-level API is just { subscribe(listener), dispatch(action), getState() }.

Provider makes it available down the React component tree via context. Connector uses subscribe(listener) to listen to changes and read from getState() when a change occurs.

These are the only essential parts.

@neverfox

This comment has been minimized.

Show comment
Hide comment
@neverfox

neverfox Jul 6, 2015

Okay, good. That's what I was able to deduce from studying Provider and Connector.

neverfox commented Jul 6, 2015

Okay, good. That's what I was able to deduce from studying Provider and Connector.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jul 7, 2015

Collaborator

I'm closing as it's not really an issue.

Collaborator

gaearon commented Jul 7, 2015

I'm closing as it's not really an issue.

@gaearon gaearon closed this Jul 7, 2015

@chikamichi

This comment has been minimized.

Show comment
Hide comment
@chikamichi

chikamichi Sep 29, 2015

Thank you @gaearon for the feedback you provided here, was most informative.

For those interested, Dan provided more insights on that very topic.

Thank you @gaearon for the feedback you provided here, was most informative.

For those interested, Dan provided more insights on that very topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment