DEV Community

Discussion on: How React isn't reactive, and why you shouldn't care

Collapse
 
brucou profile image
brucou • Edited

Fair enough. The same words may mean different things in different contexts so always good to take a tour of the landscape. IBM calls reactive systems systems that follow the reactive manifesto: reactivemanifesto.org/

Quoting:

We believe that a coherent approach to systems architecture is needed, and we believe that all necessary aspects are already recognised individually: we want systems that are Responsive, Resilient, Elastic and Message Driven. We call these Reactive Systems.

So if you talk about reactive systems to a systems architect, that is likely to be what he will understand.

If you look at academia, it is closer to what I mention, i.e. a system that continously react to external stimuli. quoting ce.pdn.ac.lk/research/complex-reac...

For these complex reactive systems, which continuously react to external stimuli (called events), we need methods and tools that permit specifying them in a precise, easy and safe way,

or here: ercim-news.ercim.eu/en67/special-t...

Many embedded systems belong to the class of reactive systems, which continuously react to inputs from the environment by generating corresponding outputs.

There is like a thousands of the same definition in papers as those folks must agree on the meaning of words before they even start to write research.

Then if you talk to web developers they will understand something else. Then how you define reactive programming is going to depend on how you define reactive systems.

When I said it does not matter, what I really mean is what matters is that you get understood, whatever words you choose to carry your meaning.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

Then if you talk to web developers they will understand something else.

In my estimation that is what Svelte is talking about when it uses the term "reactive". It takes the perspective of the "developer as a user" differentiating between "explicit change propagation" (e.g. setState()) vs. "implicit change propagation" (i.e. "reactive"). From the developer perspective Svelte has two "reactive" systems:

Example: Reactive declaration

const schedule = (delay, fn) => self.setTimeout(fn, delay);

let a = 5;

// non-reactive declaration
let b = a + 3;

// "reactive" declaration
$: bR = a + 3;

console.log(bR === 8);

schedule(100, () => {
  a += 2;
});

schedule(200, () => {
  console.log(a === 7);
  console.log(b === 8);
  console.log(bR === 10);
}); 
Enter fullscreen mode Exit fullscreen mode

So through a little syntax sugar blocks of code can become "reactive - just like you're used to from spreadsheets".
The primary appeal here is that reactivity is gained with very little adjustment of the imperative mindset of managing the flow of control - except that now reactive code automatically stays in sync with its dependencies without any explicit change propagation.
This seems to be the reactivity that most of Svelte's buzz revolves around while the "developer as a user" persona cares very little how it's implemented under the hood.

Example: Stores

import { tick } from 'svelte';
import { derived, readable, get } from 'svelte/store';

const schedule = (delay, fn) => self.setTimeout(fn, delay);

let a = readable(null, set => {
  let value = 5;
  set(value);

  schedule(100, () => {
    value += 2;
    set(value);
  });
});

// non-reactive use
// Note use of `get()` is discouraged - used for demonstration only
let b = get(a) + 3;

// "reactive" use
let bR = derived(a, $a => {
  const value = $a + 3;
  return value;
});

// use reactive declarations to use auto-subscriptions
$: aLast = $a;
$: bRlast = $bR;

tick().then(() => {
  console.log(bRlast === 8);
});

schedule(200, () => {
  console.log(aLast === 7);
  console.log(b === 8);
  console.log(bRlast === 10);
});
Enter fullscreen mode Exit fullscreen mode

Stores require a bit more explicit setup though auto-subscriptions are supposed to make consuming them more convenient. However propagation of change at the source store has to be explicitly managed by developer code - so this requires a departure from the usual "imperative flow of control" coding.

Example: Stores with explicitly managed subscriptions

import { onDestroy } from 'svelte';
import { readable } from 'svelte/store';

const schedule = (delay, fn) => self.setTimeout(fn, delay);

let a = 5;
const aStore = readable(null, set => {
  set(a);
  schedule(100, () => {
    a += 2;
    set(a);
  });
});

// non-reactive
let b = a + 3;

// "reactive" subscription
let bR;
const unsubscribe = aStore.subscribe(value => {
  bR = value + 3;
});

console.log(bR === 8);

schedule(200, () => {
  console.log(a === 7);
  console.log(b === 8);
  console.log(bR === 10);
});

onDestroy(unsubscribe);
Enter fullscreen mode Exit fullscreen mode

Without auto-subscriptions consumers have to explicitly subscribe (and unsubscribe) to stores so we're even further removed from the "imperative flow of control" model.

So stores are available for more complex use cases but would generally be judged as the least wieldy of the two options.

It's also my opinion that the adoption of RxJS was ultimately limited by the need to shift ones coding mindset away from manipulating the flow of control at runtime to writing code that largely scaffolds the transformation and routing of event streams that - once constructed - just work.

The advantage of Svelte's reactive declarations/statements is that such a shift in mindset simply isn't required - it reminds me of how the majority of developers seem to prefer using async/await (maintaining the illusion of synchronous execution) over raw Promises.