• Stars
    star
    363
  • Rank 117,374 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 8 years ago
  • Updated almost 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An attempt to make Redux and Elm applications scale

Scalable frontend, with Elm or Redux

Thanks to everyone trying to solve the problem.

Intro

The point of this specification is to see how we can build a scalable frontend architecture.

The specification remains simple compared to real-world applications, but it is meant to be kind of painful for both Redux and Elm to solve :)

This repository was created after discussions on this issue. Check it out, there are some proposed implementations that are worth checking.

What we don't try to solve here: tooling, css, ajax requests, performance...

Some observations:

  • Nested actions of Elm seems perfect for local component state but non-local interactions is not so easy
  • Flat actions of Flux/Redux seems perfect for global app state, but people still rely a lot on React this.setState for local component state.

None of these two approaches seems perfect to me. But can we have the best of both worlds?

Specification

It is based on the famous RandomGif ( JS / Elm example that is often used to showcase Elm architecture.

The app should have:

1) A NewGif component used multiple times:

NewGif is the original example component. It is used multiple times inside the app at different places. All the instances are not necessarily close to each others in the DOM tree.

  • A top-level RandomGif issuing actions like: APP_UPDATED > ... > TOP_LEVEL_RANDOM_GIF_UPDATED > NEW_GIF

  • A pair of RandomGif issuing actions like: APP_UPDATED > ... > RANDOM_GIF_PAIR > FIRST_RANDOM_GIF_UPDATED > NEW_GIF

  • A pair of pair of RandomGif issuing actions like APP_UPDATED > ... > RANDOM_GIF_PAIR_OF_PAIR_UPDATED > FIRST_RANDOM_GIF_PAIR_UPDATED > FIRST_RANDOM_GIF_UPDATED > NEW_GIF

2) A button

The button can be active or inactive. It is green when active and red when inactive. Clicking on it toggles its active state (default is inactive).

3) A counter value

The counter value should be incremented everytime a NEW_GIF action is fired from any NewGif component, no matter the nesting, but the incrementation amount is not fixed.

Business rule:

if ( ( counter >= 10 ) && ( buttonState === "active" ) ) { 
  increment by 2 
} 
else { 
  increment by 1 
}

4) The app should focus maintainability / scalability / decoupling

Somehow this problem is easy to solve in a way that creates a lot of coupling between components.

The 3 components (NewGif/Counter/Button) should be decoupled and not see each others in any way. They can't import stuff from each others. Ideally, in a JS based solutions, one could be able to publish each 3 components in separate NPM packages that don't depend on each others.

The aim of decoupling the components is that a team can take ownership of each component. Then another team is responsible of making all the components work nicely together, and you already have split the work into 4 teams.

For example, the NewGif component should not be aware of the presence of the existance of a counter, deeply hidden in a little stats popup of our app. If this counter had to be removed by the business, it's place in dom tree updated, or it's business rule be changed, the team maintaining the NewGif widget should rather not have to know about that.

It should also be easy to move the position of components. For example imagine the button is top left of your app, and the business now wants it inside a popup, bottom right: this move of component in the tree should rather be easy to make (ie without having to modify all parent components, for example).

Good luck

I don't have yet a solution for this problem but would be happy to see any proposal to solve this problem. I'd like to see solutions in any language (JS / ES6 / Elm / Typescript ...) or tech (Elm / Redux / Cycle / ...)

Hints

Here are just some ideas I or some others had on how this problem can be solved.

Submit your solution

If you would like to propose your solution, don't hesitate to.

  • Give a good name to your solution. For me something like redux-elmish-saga-slorber or elm-2mailboxes-slorber
  • Create an issue with your solution name, to get feedbacks
  • Make a pull request, create a folder with your solution name

Hire a freelance expert

Looking for a React/ReactNative freelance expert with more than 5 years production experience? Contact me from my website or with Twitter.

More Repositories

1

react-async-hook

React hook to handle any async operation in React components, and prevent race conditions
TypeScript
1,140
star
2

react-native-scroll-into-view

Scroll a ReactNative View into the visible screen. Similar to DOMElement.scrollIntoView() browser function.
TypeScript
409
star
3

awesome-debounce-promise

Debounce your API calls easily and stay in promised land.
TypeScript
376
star
4

trailing-slash-guide

Understand and fix your static website trailing slash issues!
HTML
307
star
5

gatsby-plugin-react-native-web

react-native-web plugin for Gatsby
JavaScript
277
star
6

react-native-animation-hooks

A simple declarative API for React-Native animations, using hooks
TypeScript
243
star
7

combine-promises

Like Promise.all(array) but with an object instead of an array.
TypeScript
202
star
8

rereduce

Reducer library for Redux
JavaScript
166
star
9

ajax-interceptor

This permits to wire interceptors on XHR requests and responses
JavaScript
122
star
10

react-reboot

The easiest way to refresh your React components with up-to-date syntax.
JavaScript
62
star
11

react-nested-loader

The easiest way to manage loaders/errors inside a button. NOT an UI lib.
JavaScript
62
star
12

sebastienlorber.com

My personal website
JavaScript
58
star
13

gcm-server-repository

maven repository for gcm-server for Android push notifications
Shell
46
star
14

react-native-alert-async

An Alert.alert that you can await
JavaScript
45
star
15

awesome-imperative-promise

Offer an imperative API on top of promise, with cancellation support
TypeScript
41
star
16

micro-typed-events

The smallest, most convenient typesafe TS event emitter you'll ever need
TypeScript
40
star
17

todomvc-onboarding

Showcase different ways to add a complex onboarding to a TodoMVC app
36
star
18

use-async-setState

Permits to await setState()
TypeScript
35
star
19

expo-typescript

TypeScript
33
star
20

redux-dispatch-subscribe

store enhancer for redux which allows to listen for dispatched actions
JavaScript
29
star
21

react-three-fiber-journey

Three.js Journey implemented with React-Three-Fiber
TypeScript
27
star
22

awesome-only-resolves-last-promise

Wraps an async function, and ensures that only last call will ever resolve/reject
TypeScript
26
star
23

docusaurus-crowdin-example

JavaScript
11
star
24

backspace-disabler

Disable the annoying browser backward navigation when the user press the backspace key
JavaScript
11
star
25

react-native-storage-slot

A simple typed wrapper around AsyncStorage
TypeScript
10
star
26

slorber

8
star
27

awesome-icu

Reference everything you find interesting about ICU translations
7
star
28

this-week-in-react

ThisWeekInReact.com
MDX
6
star
29

slo.im

slo.im shortcuts
4
star
30

react-updatable-context

React context which inject a value setter/updater in the Consumer
JavaScript
3
star
31

slorber-website

My website
JavaScript
2
star
32

test-docu

JavaScript
2
star
33

expo-ci

JavaScript
2
star
34

traced-svg-parameter-chooser

JavaScript
2
star
35

docusaurus-visual-tests

TypeScript
2
star
36

docusaurus-starter

JavaScript
1
star
37

bug-expokit-crashlytics

bug-expokit-crashlytics
JavaScript
1
star
38

slorber-api-screenshot

JavaScript
1
star
39

docusaurus-dsfr

TypeScript
1
star