
Things Reacters do that Re-framers avoid - zonotope
https://purelyfunctional.tv/article/react-vs-re-frame/
======
rmrfrmrf
By chance, I stumbled upon this same article a few weeks ago while re-learning
React and learning Redux.

I didn't get much out of the article since gripes 1-5 are all solved by Redux,
and 6 is a complaint about Redux having too much boilerplate.

It also seemed to me that mapStateToProps and mapDispatchToProps aren't given
a fair representation in this article (especially with the "selector" pattern
emerging within them). If your Redux store is denormalized already, then yes,
mapStateToProps will seem quite redundant. However, if you're working with
multiple sets of async data, it's _much_ easier to organize your store by
fetch method and denormalize inside mapStateToProps.

~~~
pandeiro
Having to use something like Redux, conceptually solid but so full of
boilerplate, instead of re-frame is kind of like having to use Java at work
instead of Clojure.

Some of us are just lucky, I guess.

~~~
tigroferoce
So true. Some of us are lucky enough to use a concise language like clojure. I
am really asking myself why lisp and functional programming in general are not
really taught in schools.

~~~
watwut
Functional programming is taught in schools. Sometimes even with lisp.
Students unvirsally seen it as impractical theory.

The popular ressurection of functional on frontend is relatively new
development. Before, it was used only in few math related areas.

~~~
TomMarius
Functional programming is widely used in finance.

~~~
watwut
I would count that as one member of "few math related areas".

------
erokar
> 1\. Reacters load data on mount. I want my Views to be pure. They need to
> take some data and output DOM.

At least this item comes off as a straw-man argument. Reacters also want their
views to be pure. They do not typically load data in presentational
components, and it can be easily avoided.

That said, granted: Clojure, Elm et al. achieves purity and immutability in a
simple and clean way JS/React/Redux can only approximate. The latter is for
the dirty pragmatists among us, I guess.

~~~
Groxx
Somewhat strawman, yeah. But it still seems valid - React allows you to do
this, and you do see it in the wild.

People who have been bitten by it (or read enough best-practices stuff to
avoid it up-front) will know better and won't do so, but _you have to know
better_ \- that's kinda the central point in here. React has more footguns,
and the article is arguing that they're unnecessary / things end up worse than
if they weren't allowed, without losing flexibility.

------
pcmaffey
This article fails to understand what components are in React. They are the
building blocks for every aspect of an application. My data stores are
components, my views are components, my styles are components.

The author obviously comes from an MVC background where a component is one
specific aspect of an application, and enabling it to do all these other
things seems sacrosanct. But they've got it backwards.

Think of a React component on the same level as a function: we design our
functions as purely as we can, but it's not the function's fault if it's
written poorly.

~~~
divs1210
The author also mentions why they see this property of React as a problem.

This is just like earlier versions of Java which didnt have enums or lambdas,
but used classes for everything. See what's happened now.

------
hashkb
Mobx / rxjs solves a lot of these problems for those of us who can't use cljs
or elm because our clients are afraid of them.

~~~
TomMarius
Why do you let your clients make your technological decisions?

~~~
hashkb
Because they are paying me and therefore it's not my decision. I give advice
but if the client insists on something that's what they get.

------
hakanderyal
I've built a lot of apps with React/Redux, both complex and simple ones.

At first there were lots of boilerplate code, and lots of kind-of-similar-but-
different code all around. After each project, I extracted and generalised the
helper components/methods/systems to create my own 'framework', and now I have
a foundation that eliminates most of the pain points that people experience
with react/redux, that's specific to the way I develop software. Thats why I
love React and surrounding ecosystem, it allowed me to choose the relevant
libraries/solutions that fits my workflow.

Here is my thoughts about the points in the article:

1\. Reacters load data on mount

In my components, I just declare the data that it needs, and the relevant
system loads the data and sends it to the component via props. (like Relay) No
requests happen in the component directly. When you have only a few components
that needs data in your app, fetching it in the component works, but when you
have a complex app (I build ERP systems) you need a centralised way to handle
data fetching.

2\. Reacters register a bunch of event handlers in their components

Declarative event-binding works great for me (similar to react-event-
listener[0]). Instead of adding the subscribe/cleanup logic to every
component, I just declare the events I'm interested in, and just add the
relevant handling code to my component.

3\. Reacters optimize when to render

Using redux and never overwriting the store takes care of this for me.

4\. Reacters load data when stuff changes

Same as 1., yon can declaratively state what you need, and the relevant system
can handle the rest of the logic without changing anything in the component.

5\. Reacters worry about when to set state

I'm not sure if this is really a problem, especially when you learn how the
lifecycle hooks work.

6\. Reacters use a lot of Redux boilerplate

Redux has a goal to keep things simple, and let users choose the relevant 3rd
party solution to your needs. It means that you need to do some work to create
a no-boilerplate solution, but in the end it will work flawlessly according to
your needs.

In my 'framework', I generate the store definitions and action handlers for my
database models automatically from SqlAlchemy model definitions, thus
eliminating 95% of the boilerplate.

I know that there are frameworks out there that eliminates the need to create
your own solutions to most of these problems, but I've found out that, when
you try to go out of the 'blessed' path, you will be banging your head to the
wall more times than you want. With building my own solutions around the
react/redux, I'm in control of the things that I care about. When you control
the 'magic' part of the stack you use, you have a lot of power in your hands
when problems arise.

[0]: [https://github.com/oliviertassinari/react-event-
listener](https://github.com/oliviertassinari/react-event-listener)

------
fiatjaf
What about setting a value deeply nested in your state when you change
something in a deeply nested component? What if that value is inside an array?

~~~
gleenn
Only the portion that changes will be rerendered because of the way Clojure
shares nested data structures when there are changes.

~~~
riwsky
Not quite: while Clojure does share nested data structures, and that does
allow for some neat tricks around fast comparison operations, the fact that
only changed SUV trees rerender is all due to react, and its
shouldComponentUpdate. A normal js app can get the same results, if it wants.

------
amelius
How would this work in re-frame:

Let's say I have a box with 1000 items. It will take some time to load, so
those 1000 items should not be painted in one go (freezing the UI), but
instead be shown incrementally, from top to bottom.

Imagine that while it is loading, I can click a "delete" button on one of the
items, so that item would disappear while the list is still growing at the
bottom.

~~~
TheAceOfHearts
You create a virtual list, only rendering the items visible in the viewport.
Use intersection observer or scroll events to find out when you're about to go
past the selected item.

~~~
amelius
Doesn't that cause either stuttering, or flickering in the viewport?

~~~
jaggederest
When I did this back before ajax was a thing, it was by using image elements
that were moved like a treadmill, we managed those so that there was a buffer
outside the screen area that was pre-filled to avoid stuttering. Essentially
we rendered ~1.5 screens wide / long and would fill them in a non-blocking way
when the buffer was reduced.

~~~
amelius
But when you click the scrollbar and drag it down, you can easily make the
viewport scroll by more than 2x its height in a matter of milliseconds.

I experimented with this myself, and the UI designer I worked with thought it
was not pretty when the screen turned blank while scrolling rapidly.

The problem I had was that painting the items in the viewport took already
more time than the allotted time per frame.

~~~
darkmarmot
This means the code has issues. I have virtualized data grids holding
thousands of records with each cell incorporating d3 visualizations and this
does not happen.

~~~
ridiculous_fish
Do you have a link you can share?

~~~
TheAceOfHearts
react-virtualized [0] is a great implementation of a virtualized list using
ReactJS.

[0] [https://bvaughn.github.io/react-
virtualized/#/components/Lis...](https://bvaughn.github.io/react-
virtualized/#/components/List)

------
frigen
I agree that reactjs would have been better without setstate, instead with
tightly integrated Redux, which would remove much of the Redux boilerplate.

For the most part, this is what this reframe thing aims at as far as I can
tell.

Setstate really should be long term deprecated, it's a design error in react.

~~~
mercurial
No, it's really about knowing what is global and what is local. You have
plenty of things for which local state makes sense.

~~~
frigen
True, but ideally the framework would lead programmers automatically to ways
of doing things in the "right way" instead of overusing local state.

A "better react" would make it natural and obvious to use store versus local
state in the appropriate way.

~~~
mercurial
Well, that's not really the idea behind React. You could say local storage is
more a convenience than anything, React is primarily about rendering your
data.

The problem is that, with Redux at least, composing data stores is a major
pain. The only pattern supported out-of-the-box is horizontal slicing (have
different reducer for separate pieces of data). This may work for separate
pages, but it does nothing for you as soon as you need data sharing. I don't
think React itself should change, but I haven't found a really satisfactory
solution to the problem of sharing stored data.

------
ridiculous_fish
How do Re-framers handle components that wants to redraw using a timer, such
as an animation or progress bar?

~~~
serpix
you would normally start setInterval/whatever function somewhere and you
dispatch the change to re-frame when needed. Reframe will update the db and
the components subscribing to that data will redraw when a change occurs. The
component(s) themselves have no coupling whatsoever to what is providing the
displayed data.

------
hartator
'componentDidMount' doesn't exist anymore in React es6.

~~~
haukur
It still does (these docs use the ES6 class API):
[https://facebook.github.io/react/docs/react-
component.html#c...](https://facebook.github.io/react/docs/react-
component.html#componentdidmount)

