Hacker News new | ask | show | jobs
by kalkut 2900 days ago
You can make any suitable variation of the following pattern.

You build a DataSource class/prototype with methods such as :

- fetch

- addChangeListener

- removeChangeListener

You extend this class for each data type :

  class CommentsData extends DataSource {
    // Your custom data source with your data treatment and data getters
  }
And you use the Higher-Order Component pattern: https://reactjs.org/docs/higher-order-components.html
1 comments

That's just a more Object Oriented Redux (or less, if we consider OOP is originally message passing), and probably without all the connect optimizations.

I'm not a fan of Redux either, but I fail to see what problems this approach solves.

> That's just a more Object Oriented Redux

> I fail to see what problems this approach solves.

You are absolutely right I gave an ad-hoc Redux as an example of Higher-Order Component.

Being OOP or not is only a matter of implementation of your data source. Here you have absolute control on it and depending on the type of your data, the frequency at which it is updated or its (a)synchronicity, you may prefer/need something very different from a dispatcher/action/reducer system.

The real pattern here is the HCO and yes Redux also use this pattern to build "smart components" with "dumb" ones. But it does it in a very opinionated way.

As an example : for performance reasons you really don't want Redux to handle real-time data with very frequent updates, it is better to manage this kind of data your own way.

A more common case is having only a few amount of data that have to be shared across the tree (things like an user session or the chosen language). If your component tree has too many level of depth an ad-hoc solution can do fine here.

IMHO there is two type of arguments for why Redux might not be needed :

1) A reasonable UI respects separation of concerns.

There should be limited need for data exchanges or interactions between two unrelated components. Making the data flow from the local state of a "smart component" is fine most of the time.

2) What Redux does can be done with less boilerplate when and where it is needed.

You can make your component "smart" in a lot of ways. It can be done with pure React state management, it can be done with custom data sources and HCO, it can be done with JavaScript CustomEvents and so on.

The worst problem here is that because Redux is a (very good) opinionated abstraction, lots of developers forget it is a library and not a framework so they try to find what they think is the most Redux-way of doing things. I've seen tons of projects that ended up being a mess of Redux/Thunk/Reselect plus whatever middlewares where updating a single property implies at least handling it in the reducer, adding a selector, and adding the result in mapStateToProps. Redux is definitely not a bad solution but in becoming a standard one it hurt a lot of projects.

This situation is very well explained by pcstl above when he says

> People mainly use Redux because they don't understand that React isn't Angular.

> Redux is what you get when people try to use React as a "full-app" framework instead of what it's meant to be: a view layer.

What connect optimizations? Redux is quite slow.
`connect` does a _lot_ of work to ensure that your own components only re-render when necessary:

- It checks to see if the root Redux state is different than last time, and bails out if it's the same reference under the assumption that nothing changed

- It checks to see if the return values from your `mapState` function are shallow-equality different than last time, and again bails out if they're the same

- The handling for `mapState` and `mapDispatch` is heavily memoized to cut down on unneeded work.

If you have specific performance concerns with a Redux app, please let me know - I'd be happy to offer advice and point you to possible solutions. But, a blanket statement that "Redux is quite slow" is meaningless without context for what's happening.

In large apps mapStateToProps gets called when things my component doesn't care about change - its a simple downside to having one global store as a design.

We now speed things up buy removing redux and just using events with multiple stores anyone can access - we can easily tune the system and don't have to rely on magic that can never be as efficient. Plus the syntax is much cleaner.

Dispatch is another big culprit.

I have exactly the same experience and implemented the same solution. An ex-colleague also did the same thing. We both worked on collaborative webapps but in different companies at the time so performance gain was very important.

I still use Redux on some projects but I definitely start the new ones without thinking about it.

> Dispatch is another big culprit.

Could you clarify what you mean by that?

Per both of your comments: generally speaking, your `mapState` functions _should_ run as quickly as possible. Ideally, a `mapState` function should just grab a couple values from the Redux state object and return those.

If a component needs the store data to be transformed in some way, we recommend using memoized selector functions [0] to cut down on unnecessary work.

So, in a well-written app, your `mapState` functions shouldn't be bottlenecks.

As I said, if you've got some examples of specific perf issues, I'd be happy to offer advice.

[0] https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-us...