SlideShare a Scribd company logo
1 of 64
Download to read offline
The battle of react global state
managers in web applications
Evangelia Mitsopoulou
Founder | Senior Frontend Engineer | Semantic Web Analyst | Writer
evangelia.me
https://www.linkedin.com/in/evangelia-mitsopoulou-
5765135/
20.02.24 - GreeceJS, Impact Hub Athens
Data Fetching Flow during first Page Load
Proxy Server Database
Browser
cache
1. Data transformation
2. Data binding
3. Data rendering
4. Data visualization
Data fetching
js- logic
Data fetching
Data Fetching Flow during first Page Load
Loading State
Error State
Concurrency
Rendered Data
Data Update Flow after first Page Load
HTTP
HTTP
HTTP
Problems to solved by global state
■ Issues with Predictable State Changes
■ Performance issues
■ Lack of Consistency
■ Concurrency issues
■ Caching issues
■ Scalability Testing and time travel debugging
When do we need a global state?
■ Complex applications with dependencies of data
■ Server side data fetching as database cache
■ Repeated calculations
■ Deep nested component hierarchies
■ Share User-input data
■ Broadcast messaging on event driven communication
■ Centralized handling of loading indicator
State management is …
■ How we handle the transition from one state to the other
State
Manager
Conceptual Framework
Atomic
03 ● Breaks down state into smaller,
independent pieces
Unidirectional
01
● Data flow towards one
direction, from store to the
components
Reactive
02
● Focus on automatic updates at
the components based on
changes on the state
State Machines
04
● Collection of finite states,
events and transitions between
states. Local state friendly
Conceptual Framework
Cache Friendly
05
● Works well with data fetching,
caching, retries, deduping and
synching,
React Built-in
06
● Data needs to be accessible by
many components at different
nested levels
React State Managers
Ecosystem Redux
Zustand
Vuex/Pinia
Ngrx/Store
MobX
Valtio
Akita
XState
Hooks + Context
Hooks + Props
Drilling
Reactive
Recoil
Jotai
Atomic Finite State Machines
Unidirectional
React Built-in
React Query
Data fetching friendly
SWR
Unidirectional Redux Toolkit
Increment
Component A
dispatch action
CounterSlice
Reducer
State
rerender/reacts
update/mutate
copy
Component B
Counter
rerender/reacts
{ .. }
(js-object)
Remember?
Counter: 1
{
type: 'INCREMENT'
payload '1'
}
(useSelector)
(dispatch(increment()
))
(useSelector)
Store
Redux-toolkit - Slices
import { configureStore, createSlice } from "@reduxjs/toolkit"
export interface CounterInitialState {
counter: number;
}
const counterInitialState: CounterInitialState = {
counter: 0;
}
const counterSlice: createSlice = ( {
name: "counter",
initialState: counterInitialState,
reducers: { increment: (state) => { state.counter +=1; } }
} )
export const store = configureStore ( {
reducer: {
counter: counterSlice.reducer,
},
} );
type RootState = ReturnType <typeof store.getState>;
export const selectCounter = ( state: RootState ) => state.counter;
export const { increment} => counterSlice.actions;
Redux-toolkit - Store/reducers
Redux-toolkit - Root App
const App: React.FunctionComponent = ( ) => (
<Provider store= {store}>
<div>
<h1>Unidirectional - Redux Toolkit</h1>
< IncrementButton/>
< Counter/>
</div>
</Provider>
);
export default App;
import { store } from "/.store";
import { Provider } from "react-redux";
Redux-toolkit - App Usage - Counter
import { selectCounter } from "/.store";
import { useSelector } from "react-redux";
const Counter: React.FunctionComponent = ( ) => {
const counter = useSelector (selectCounter) ;
return (
<div>
<span>Counter</span>
<div> { counter } </div>
</div>
) ;
};
Redux-toolkit - App Usage - Increment
import { store, increment, selectCounter } from "/.store";
import { useDispatch } from "react-redux";
const IncrementButton: React.FunctionComponent = ( ) => {
const dispatch = useDispatch ( ) ;
return (
<button onClick={ ( ) => dispatch( increment ( )) }>
Increment
</button>
) ;
};
Bidirectional/Reactive: MobX
Increment
Component A
Component B
Counter
observer
● *Implemented as class
● All properties are marked as
observable so that they are
tracked
Remember?
observer
react:rerender
action/update value
CounterStore
State
observable values*
f1
actions
f2
Counter: 1
MobX - Store
import { makeAutoObservable, observable } from "mobx"
class ApplicationStore {
counter = 0;
trials = 0;
constructor ( ) { makeAutoObservable (this, { })}
increment ( ) { this.counter += 1;}
decrement ( ) { this.counter -= 1;}
}
const store = new ApplicationStore ( );
export default store;
MobX - Counter/Increment Components
import { observer } from "mobx-react-lite"
import store from "./store"
const Counter: React.FunctionComponent = observer ( ( ) ) => (
<div>
<span>Counter</span>
<div> { store.counter } </div>
</div>
));
const IncrementButton: React.FunctionComponent = observer ( ( ) ) => (
<button onClick={ ( ) => store.increment ( ) }> Increment </button>) ;
};
MobX - RootApp
const App: React.FunctionComponent = ( ) => (
<div>
<h1>Unidirectional - MobX</h1>
<IncrementButton/>
<Counter/>
</div>
);
export default App;
Atomic: Recoil
Atom1
{
key: counter
default: '0''
}
Remember?
Component A
Increment
Component B
Decrement
Component C
View Total
Transactions
Selector 1
set get
get
get
{
key: 'increment'
default: '0'',
get: ({get})=>get(Atom1)*3
}
Selector 2
{
key: 'increment'
default: '0'',
get: ({get})=>get(Atom1) +
get(Atom2) + get(Atom3)
}
useSetRecoilState()
derives from
derives from
derives from derives from
. . .
. . .
Atom2
{
key: Products
default: '12''
}
. . .
. . .
Atom3 { .. }
(js-object)
. . .
. . .
Recoil - Atom Definition
import { useEffect } from "react"
import { atom, useRecoilSate, useRecoilValue, selector } from "recoil"
type Product = {
id: string;
name: string;
description: string;
onSale: boolean;
}
export const counterValueAtom = atom <number> ({
key: "counterValue",
default: 0,
})
Recoil - Atom & Selector definition
import { useEffect } from "react"
import { atom, useRecoilSate, useRecoilValue, selector } from "recoil"
export const productsAtom = atom <number> ({
key: "products",
default: [ ],
})
export const discountProductsAtom = selector <number> ({
key: "discountProductsAtom",
get: ({ get }) => {
const products = get (productsAtom);
return products?.filter( ( item) => item.onSale );
},
});
Recoil - Counter
import { useRecoilValue, useRecoilSate, RecoilRoot } from "recoil"
import { counterValueAtom, productsAtom, useProducts } from "./store"
const Counter: React.FunctionComponent = ( ) => {
const counter = useRecoilValue (counterValueAtom);
return (
<div>
<span>Counter</span>
<div> { counter } </div>
</div>
);
};
Recoil - Increment Button
import { useRecoilSate} from "recoil"
import { counterValueAtom, } from "./store"
const IncrementButton: React.FunctionComponent = ( ) => {
const [counter, setCounter] = useRecoilSate (counterValueAtom);
return (
<div>
<button onClick={ ( ) => setCounter ( counter + 1) }>
Increment
</button>) ;
</div>
);
};
Recoil - Products
const Products: React.FunctionComponent = ( ) => {
const products = useRecoilValue (productsAtom);
const discounts = useRecoilValue (productsAtom);
return (
<div>
<div> Products </div>
{products.map( ( product ) => {
return (
<div> {product.name} + {product.description} </div> )}};
<div> Number of Discounts </div>
<div> { discounts?.length} </div>
</div>
) }
Recoil - AppRoot
const App: React.FunctionComponent = ( ) => {
useProducts ( );
return (
<div>
<h1> Atomic - Recoil </h1>
<Counter />
<IncrementButton/>
<Products />
</div>
) ;
};
export default ( ) => (< RecoilRoot> < App/></RecoilRoot> )
React Query
■ It is an async state manager
■ Comes with smart fetching, caching, synchronising, and updating the server
state (persistent state) in your react application
Client State
URL / Router
Server State
Client
LocalStorage, Session
Storage, Cache API,
Cookies, IndexedDB
Persistent State
Why React Query?
■ Simplifies data fetching - Erases a lot of boilerplate and makes
your code easy to read.
■ Improves the reliability of server data by invalidates them
■ Provides tools to improve User Experience - Prefetching, re-
fetching, caching, and more.
■ Performance optimisations - Pagination and lazy loading.
■ Request Retries - Ability to retry in case of errors.
■ Window Focus Refetching - Refetching based on application tab
activity
TanStack Query
■ Formerly known as React Query v3
■ Aims to make the React Query async state manager, available
to frameworks beyond React, and comes with a variety of new
features
■ It exists now for
○ React @tanstack/react-query (React Query v4)
○ Svelte @tanstack/svelte-query
○ Solid @tanstack/solid-query
○ Vue @tanstack/vue-query
React Query- Types
import React, { useSate, createContext, useContext } from "react"
import { atom, useRecoilSate, useRecoilValue, selector } from "react-query"
type Product = {
id: string;
name: string;
description: string;
onSale: boolean;
}
interface ApplicationSate {
counter: number;
products?: Product [ ];
increment: ( ) => void;
}
React Query - ApplicationContext
const ApplicationContext: React.FunctionComponent = ( ) => {
const { movie} = createContext<ApplicationState> ( {
counter: 0,
products?: [ ],
increment: ( ) => { },
} );
import React, { useState, createContext, useContext } from 'react'
React Query - useApplicationState
const useApplicationState = ( ) : ApplicationState => {
const { counter, setCounter} = useState (0) ;
const { data } = useQuery<{
products: Product [ ];
}>( "products", ( ) => fetch ("/products.json ). then( (res ) => res.json( )), {
enabled: counter > 2,
})
return {
counter,
increment: ( ) => setCounter( counter+1),
products: data?.products,
}
}
React Query - contextProvider
const queryClient = new QueryClient ( );
const CounterItemsContextProvider : React.FunctionComponent = ( { children } ) =>
<ApplicationContext.Provider value = { useApplicationState( )}>
{children}
</ApplicationContext.Provider> );
export const ApplicationContextProvider : React.FunctionComponent = ( { children } ) => (
<QueryClientProvider client = { queryClient } >
<CounterItemsContextProvider> {children} </CounterItemsContextProvider>
</QueryClientProvider >
);
export const useApplicationContext = ( ) => useContext(ApplicationContext)
ReactQuery - Counter
import { useApplicationContext, ApplicationContextProvider } from "./store'
const Counter: React.FunctionComponent = ( ) => {
const { counter } = useApplicationContext ( );
return (
<div>
<span>Counter</span>
<div> { counter } </div>
</div>
);
};
ReactQuery - Increment Button
import { useApplicationContext, ApplicationContextProvider } from "./store'
const IncrementButton: React.FunctionComponent = ( ) => {
const { increment } = useApplicationContext ( );
return (
<div>
<button onClick={ ( ) => increment ( ) }> Increment </button>
</div>
);
};
ReactQuery - Products
const Products: React.FunctionComponent = ( ) => {
const { products } = useApplicationContext ( );
return (
<div>
<div> Products </div>
{products.map( ( product ) => {
return (
<div> {product.name} + {product.description} </div> )}};
</div>
) }
ReactQuery - AppRoot
const App: React.FunctionComponent = ( ) => (
<ApplicationContextProvider>
<div>
<h1> API - React Query </h1>
<IncrementButton/>
<Products />
<Counter />
</div>
</ApplicationContextProvider>
);
export default App;
State machines: Definition
■ Maths: A finite state machine is a mathematical model of
computation that describes the behavior of a system that
can be in only one state at any given time
■ Frontend: State machines are a formal and declarative way
to model and manage the state of an application. They
define all possible finite states that an application can go
through. Through events we can transite from one state to
the other
State machines UI Development
Finite State: is like a Behavior
which depending on the state
behaves different on events i.e.
click Play Button
State Video Playing
State Video Paused
click(PlayButton)
click(Pause Button)
Behavior C
State Machine
State Video not started
Behavior A
Behavior B
Traditional Event-driven UI Development
Init State
■ There is almost infinite set
of things that can be done
to a UI
■ Each element has a wide
range of possible mutations
Same state, different values on its
UI properties, after triggering events
State Machines - Core Concepts
■ Statecharts: Built on top of state machines for more
complicated mechanics
■ Actor Model: An actor is an own entity which can have its one
state machines or statecharts
■ Not tight to a framework or language
■ Local State first. Use Context for global state
■ XState is a JavaScript/TypeScript implementation of finite
state machines and statecharts. It is like useReducer, for local
Components state. Could be used globally as well in
collaboration with context or useQuery
State Machines - Core Concepts
State machines Visualizer
XState - ApplicationContext
const ApplicationContext = createContext <ApplicationState> ( {
frame: 0,
thumbnail: ' ',
counter: 0,
movie: { url: ' ', thumbnail: ' ' },
running: false,
onPlay: ( ) => { },
onPause: ( ) => { },
onResume: ( ) => { },
} );
XState - useApplicationState
const useApplicationState = ( ) : ApplicationState => {
const [ state, send ] = useMachine (videoMachine);
return {
thumbnail: state.context.thumbnail,
frame: state.context.frame,
counter: state.context.counter,
movie: state.context.movie,
running: state.value !== "notstarted" && state.value !== "paused" &&
state.value !== "pausing"
onPlay: ( ) => send("PLAY"),
onResume: ( ) => send("RESUME"),
onPause: ( ) => send("PAUSE"),
} ;
};
XState - ApplicationContextProvider
export const ApplicationContextProvider: React.FunctionComponent = ({ children } ) => (
<ApplicationContext.Provider value={useApplicationState( )}>
{ children }
</ApplicationContext.Provider>
);
export const useApplicationContext = ( ) => useContext(ApplicationContext);
XState - videoMachine
const videoMachine = createMachine<VideoContext, VideoContent> ( {
id: "video",
initial: "notstarted",
context: { frame 0, movie: { url: '', thumbnail '', counter 0 } },
states: {
notstarted: { on: { PLAY: "started" } },
started: {
invoke: { id: "getMovie", src: (context, event)=> fetchMovie(),
onDone: { target: "success", } actions: assign({ movie:}),
on: { PAUSE: "paused" } },
paused: { on: { RESUME: "resumed" } },
starting: {} },
} )
XState - Types
import React, { createContext, useContext } from 'react'
import { useMachine } from '@xstate/react'
import { createMachine, assign } from 'xstate'
type VideoEvent = { type: "PLAY" } | { type: "PAUSE" } | { type: "STOP" } |
{ type: "RESUME" };
type VideoContext = {
thumbnail: string;
frame: number;
counter: number;
movie: Movie;
};
type Movie = { url: string; thumbnail: string; };
XState - LoadingStatus
import { useApplicationContext } from './store'
const LoadingStatus: React.FunctionComponent = ( ) => {
const { running, onPlay, onPause } = useApplicationContext ( );
return (
<div className="my-5">
<button onClick = {running ? onPause : onPlay } >
{ running ? "Pause" : "Start" }
</button>
</div>
);
};
XState - Movie
import { useApplicationContext } from './store'
const Movie: React.FunctionComponent = ( ) => {
const { movie} = useApplicationContext ( );
return movie.url ? (
<>
<div>Movie</div>
<video> { } </video>
</>
) : (
<img src={ movie.thumbnail } />
);
};
XState - App
import { ApplicationContextProvider } from './store'
const App: React.FunctionComponent = ( ) => {
<ApplicationContextProvider>
<div>
<h1> XState</h1>
< LoadingState/>
< Movie/>
</div>
</ApplicationContextProvider>
};
export default App;
Metrics Comparison Table
Feature Redux MobX Recoil Ngrx/Store Vuex XState
Immutability Enforces
immutability
through
reducers
Mutable
observables
Mutable atom
values
Enforces
immutability
through
reducers
Enforces
immutabilit
y through
mutations
Emphasizes
immutability
through state
machines
Predictability Actions,
Reducers,
Centralized
Store
Reactive
programming,
Observables
Atom-based
state
management
Actions,
Reducers,
Centralized
Store
Actions,
Mutations,
Centralize
d Store
Finite State
Machines,
State Charts
Metrics Comparison Table
Feature Redux MobX Recoil Ngrx/Store Vuex XState
Concurrency Limited due to
single state
tree
Good support
for
concurrency
with reactions
Limited
support for
concurrent
reactions
Supports
concurrency
through
actions
Supports
concurrency
through
mutations
Built with
concurrency
in mind
Performance Efficient update
through
Redux's diffing
Efficient due
to reactive
updates
Efficient,
but
depends
how atoms
are used
Efficient with
selective
memoization
Efficient
with Vue's
reactivity
system
Emphasizes
efficiency in
state
transitions
State Manager Destructuring
Fetching - Caching
Server state
TanStack Query
All possible states
Fetching
fetch/axios/http
Framework agnostic pieces
State Machines
Handling Async
Rxjs,
Middlewares,
Promises
Client state
Composable atomic
units
Server-side
rendering
Future trends for state management
■ Move away from monolithic solutions like Redux to more
atomic ones like Recoil, Zustand
■ Emphasis on composability and reusability
■ Emphasis on developer experience
■ Cache friendly
■ Server side state management
Thank you!
Data Transformation
■ Change name convention: i.s snake_case them
■ Add new fields for data normalization: key / id
■ Make data type-safe and on the desired shape for runtime
because Typescript solves problems during compilation time.
Data binding
data: [ {
id: '1',
description: 'test2',
image: url ('http://1')
},
id: '2',
description: 'test2',
image: url ('http://2')
} ]
data.json
video.json
video:
{
id: '1',
title: 'my video',
url: url ('http://1')
}
Source Code
Browser
Data binding
data: [
{
id: '1',
description: description item 1,
thumbnail: url ('http://1')
},
id: '2',
description: 'test2',
thumbnail: url ('http://2')
}]
data.json
Source Code
Browser
Data rendering
■ The process of generating visual representation based on input
data or instructions
■ Templating (Render Tree Construction)
○ HTML Parsing - Bytes -Tokenization - Nodes
■ DOM Construction
■ CSSOM Construction
■ Layouting
○ Mathematical calculation of the size and position of the
nodes
■ Painting
○ Actual positioning of the calculated elements on the screen
Concurrency
■ Definition: The ability of a web application to manage and execute
multiple tasks simultaneously
○ Rendering user interface
○ Making asynchronous requests
○ Processing user interactions in a non-blocking way
○ Service Workers
○ Error handling
Concurrency
■ Key aspects
○ Asynchronous programming
○ Multithreading - Web Workers
○ Event Loop
○ Concurrency control (throttling, debouncing)
○ Service Workers
○ Error handling
State: Definition
■ The state is just a snapshot or representation of the
system from the client-side at a given point in time
■ It includes things such as:
○ User preferences
○ User input
○ Navigation information
○ Fetched Data from API

More Related Content

Similar to Battle of React State Managers in frontend applications

React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practicesClickky
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
What 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architecturesWhat 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architecturesFrancesco Di Lorenzo
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to HooksSoluto
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기NAVER SHOPPING
 
Beginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native appBeginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native appKaty Slemon
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentArtur Szott
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react applicationGreg Bergé
 
Damian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxDamian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxPROIDEA
 
Vuex to Pinia, how to migrate an existing app
Vuex to Pinia, how to migrate an existing appVuex to Pinia, how to migrate an existing app
Vuex to Pinia, how to migrate an existing appDenny Biasiolli
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneCommit University
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsMihail Gaberov
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxLoiane Groner
 

Similar to Battle of React State Managers in frontend applications (20)

React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
React redux
React reduxReact redux
React redux
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
What 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architecturesWhat 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architectures
 
react.pdf
react.pdfreact.pdf
react.pdf
 
React with Redux
React with ReduxReact with Redux
React with Redux
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기
 
Beginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native appBeginner’s tutorial (part 2) how to integrate redux-saga in react native app
Beginner’s tutorial (part 2) how to integrate redux-saga in react native app
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
Damian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxDamian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with Redux
 
React outbox
React outboxReact outbox
React outbox
 
Vuex to Pinia, how to migrate an existing app
Vuex to Pinia, how to migrate an existing appVuex to Pinia, how to migrate an existing app
Vuex to Pinia, how to migrate an existing app
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIs
 
Intro react js
Intro react jsIntro react js
Intro react js
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
 

Recently uploaded

Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsYoss Cohen
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 

Recently uploaded (20)

Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platforms
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 

Battle of React State Managers in frontend applications

  • 1. The battle of react global state managers in web applications Evangelia Mitsopoulou Founder | Senior Frontend Engineer | Semantic Web Analyst | Writer evangelia.me https://www.linkedin.com/in/evangelia-mitsopoulou- 5765135/ 20.02.24 - GreeceJS, Impact Hub Athens
  • 2. Data Fetching Flow during first Page Load Proxy Server Database Browser cache 1. Data transformation 2. Data binding 3. Data rendering 4. Data visualization Data fetching js- logic Data fetching
  • 3. Data Fetching Flow during first Page Load Loading State Error State Concurrency Rendered Data
  • 4. Data Update Flow after first Page Load HTTP HTTP HTTP
  • 5. Problems to solved by global state ■ Issues with Predictable State Changes ■ Performance issues ■ Lack of Consistency ■ Concurrency issues ■ Caching issues ■ Scalability Testing and time travel debugging
  • 6. When do we need a global state? ■ Complex applications with dependencies of data ■ Server side data fetching as database cache ■ Repeated calculations ■ Deep nested component hierarchies ■ Share User-input data ■ Broadcast messaging on event driven communication ■ Centralized handling of loading indicator
  • 7. State management is … ■ How we handle the transition from one state to the other State Manager
  • 8. Conceptual Framework Atomic 03 ● Breaks down state into smaller, independent pieces Unidirectional 01 ● Data flow towards one direction, from store to the components Reactive 02 ● Focus on automatic updates at the components based on changes on the state State Machines 04 ● Collection of finite states, events and transitions between states. Local state friendly
  • 9. Conceptual Framework Cache Friendly 05 ● Works well with data fetching, caching, retries, deduping and synching, React Built-in 06 ● Data needs to be accessible by many components at different nested levels
  • 10. React State Managers Ecosystem Redux Zustand Vuex/Pinia Ngrx/Store MobX Valtio Akita XState Hooks + Context Hooks + Props Drilling Reactive Recoil Jotai Atomic Finite State Machines Unidirectional React Built-in React Query Data fetching friendly SWR
  • 11. Unidirectional Redux Toolkit Increment Component A dispatch action CounterSlice Reducer State rerender/reacts update/mutate copy Component B Counter rerender/reacts { .. } (js-object) Remember? Counter: 1 { type: 'INCREMENT' payload '1' } (useSelector) (dispatch(increment() )) (useSelector) Store
  • 12. Redux-toolkit - Slices import { configureStore, createSlice } from "@reduxjs/toolkit" export interface CounterInitialState { counter: number; } const counterInitialState: CounterInitialState = { counter: 0; } const counterSlice: createSlice = ( { name: "counter", initialState: counterInitialState, reducers: { increment: (state) => { state.counter +=1; } } } )
  • 13. export const store = configureStore ( { reducer: { counter: counterSlice.reducer, }, } ); type RootState = ReturnType <typeof store.getState>; export const selectCounter = ( state: RootState ) => state.counter; export const { increment} => counterSlice.actions; Redux-toolkit - Store/reducers
  • 14. Redux-toolkit - Root App const App: React.FunctionComponent = ( ) => ( <Provider store= {store}> <div> <h1>Unidirectional - Redux Toolkit</h1> < IncrementButton/> < Counter/> </div> </Provider> ); export default App; import { store } from "/.store"; import { Provider } from "react-redux";
  • 15. Redux-toolkit - App Usage - Counter import { selectCounter } from "/.store"; import { useSelector } from "react-redux"; const Counter: React.FunctionComponent = ( ) => { const counter = useSelector (selectCounter) ; return ( <div> <span>Counter</span> <div> { counter } </div> </div> ) ; };
  • 16. Redux-toolkit - App Usage - Increment import { store, increment, selectCounter } from "/.store"; import { useDispatch } from "react-redux"; const IncrementButton: React.FunctionComponent = ( ) => { const dispatch = useDispatch ( ) ; return ( <button onClick={ ( ) => dispatch( increment ( )) }> Increment </button> ) ; };
  • 17. Bidirectional/Reactive: MobX Increment Component A Component B Counter observer ● *Implemented as class ● All properties are marked as observable so that they are tracked Remember? observer react:rerender action/update value CounterStore State observable values* f1 actions f2 Counter: 1
  • 18. MobX - Store import { makeAutoObservable, observable } from "mobx" class ApplicationStore { counter = 0; trials = 0; constructor ( ) { makeAutoObservable (this, { })} increment ( ) { this.counter += 1;} decrement ( ) { this.counter -= 1;} } const store = new ApplicationStore ( ); export default store;
  • 19. MobX - Counter/Increment Components import { observer } from "mobx-react-lite" import store from "./store" const Counter: React.FunctionComponent = observer ( ( ) ) => ( <div> <span>Counter</span> <div> { store.counter } </div> </div> )); const IncrementButton: React.FunctionComponent = observer ( ( ) ) => ( <button onClick={ ( ) => store.increment ( ) }> Increment </button>) ; };
  • 20. MobX - RootApp const App: React.FunctionComponent = ( ) => ( <div> <h1>Unidirectional - MobX</h1> <IncrementButton/> <Counter/> </div> ); export default App;
  • 21. Atomic: Recoil Atom1 { key: counter default: '0'' } Remember? Component A Increment Component B Decrement Component C View Total Transactions Selector 1 set get get get { key: 'increment' default: '0'', get: ({get})=>get(Atom1)*3 } Selector 2 { key: 'increment' default: '0'', get: ({get})=>get(Atom1) + get(Atom2) + get(Atom3) } useSetRecoilState() derives from derives from derives from derives from . . . . . . Atom2 { key: Products default: '12'' } . . . . . . Atom3 { .. } (js-object) . . . . . .
  • 22. Recoil - Atom Definition import { useEffect } from "react" import { atom, useRecoilSate, useRecoilValue, selector } from "recoil" type Product = { id: string; name: string; description: string; onSale: boolean; } export const counterValueAtom = atom <number> ({ key: "counterValue", default: 0, })
  • 23. Recoil - Atom & Selector definition import { useEffect } from "react" import { atom, useRecoilSate, useRecoilValue, selector } from "recoil" export const productsAtom = atom <number> ({ key: "products", default: [ ], }) export const discountProductsAtom = selector <number> ({ key: "discountProductsAtom", get: ({ get }) => { const products = get (productsAtom); return products?.filter( ( item) => item.onSale ); }, });
  • 24. Recoil - Counter import { useRecoilValue, useRecoilSate, RecoilRoot } from "recoil" import { counterValueAtom, productsAtom, useProducts } from "./store" const Counter: React.FunctionComponent = ( ) => { const counter = useRecoilValue (counterValueAtom); return ( <div> <span>Counter</span> <div> { counter } </div> </div> ); };
  • 25. Recoil - Increment Button import { useRecoilSate} from "recoil" import { counterValueAtom, } from "./store" const IncrementButton: React.FunctionComponent = ( ) => { const [counter, setCounter] = useRecoilSate (counterValueAtom); return ( <div> <button onClick={ ( ) => setCounter ( counter + 1) }> Increment </button>) ; </div> ); };
  • 26. Recoil - Products const Products: React.FunctionComponent = ( ) => { const products = useRecoilValue (productsAtom); const discounts = useRecoilValue (productsAtom); return ( <div> <div> Products </div> {products.map( ( product ) => { return ( <div> {product.name} + {product.description} </div> )}}; <div> Number of Discounts </div> <div> { discounts?.length} </div> </div> ) }
  • 27. Recoil - AppRoot const App: React.FunctionComponent = ( ) => { useProducts ( ); return ( <div> <h1> Atomic - Recoil </h1> <Counter /> <IncrementButton/> <Products /> </div> ) ; }; export default ( ) => (< RecoilRoot> < App/></RecoilRoot> )
  • 28. React Query ■ It is an async state manager ■ Comes with smart fetching, caching, synchronising, and updating the server state (persistent state) in your react application Client State URL / Router Server State Client LocalStorage, Session Storage, Cache API, Cookies, IndexedDB Persistent State
  • 29. Why React Query? ■ Simplifies data fetching - Erases a lot of boilerplate and makes your code easy to read. ■ Improves the reliability of server data by invalidates them ■ Provides tools to improve User Experience - Prefetching, re- fetching, caching, and more. ■ Performance optimisations - Pagination and lazy loading. ■ Request Retries - Ability to retry in case of errors. ■ Window Focus Refetching - Refetching based on application tab activity
  • 30. TanStack Query ■ Formerly known as React Query v3 ■ Aims to make the React Query async state manager, available to frameworks beyond React, and comes with a variety of new features ■ It exists now for ○ React @tanstack/react-query (React Query v4) ○ Svelte @tanstack/svelte-query ○ Solid @tanstack/solid-query ○ Vue @tanstack/vue-query
  • 31. React Query- Types import React, { useSate, createContext, useContext } from "react" import { atom, useRecoilSate, useRecoilValue, selector } from "react-query" type Product = { id: string; name: string; description: string; onSale: boolean; } interface ApplicationSate { counter: number; products?: Product [ ]; increment: ( ) => void; }
  • 32. React Query - ApplicationContext const ApplicationContext: React.FunctionComponent = ( ) => { const { movie} = createContext<ApplicationState> ( { counter: 0, products?: [ ], increment: ( ) => { }, } ); import React, { useState, createContext, useContext } from 'react'
  • 33. React Query - useApplicationState const useApplicationState = ( ) : ApplicationState => { const { counter, setCounter} = useState (0) ; const { data } = useQuery<{ products: Product [ ]; }>( "products", ( ) => fetch ("/products.json ). then( (res ) => res.json( )), { enabled: counter > 2, }) return { counter, increment: ( ) => setCounter( counter+1), products: data?.products, } }
  • 34. React Query - contextProvider const queryClient = new QueryClient ( ); const CounterItemsContextProvider : React.FunctionComponent = ( { children } ) => <ApplicationContext.Provider value = { useApplicationState( )}> {children} </ApplicationContext.Provider> ); export const ApplicationContextProvider : React.FunctionComponent = ( { children } ) => ( <QueryClientProvider client = { queryClient } > <CounterItemsContextProvider> {children} </CounterItemsContextProvider> </QueryClientProvider > ); export const useApplicationContext = ( ) => useContext(ApplicationContext)
  • 35. ReactQuery - Counter import { useApplicationContext, ApplicationContextProvider } from "./store' const Counter: React.FunctionComponent = ( ) => { const { counter } = useApplicationContext ( ); return ( <div> <span>Counter</span> <div> { counter } </div> </div> ); };
  • 36. ReactQuery - Increment Button import { useApplicationContext, ApplicationContextProvider } from "./store' const IncrementButton: React.FunctionComponent = ( ) => { const { increment } = useApplicationContext ( ); return ( <div> <button onClick={ ( ) => increment ( ) }> Increment </button> </div> ); };
  • 37. ReactQuery - Products const Products: React.FunctionComponent = ( ) => { const { products } = useApplicationContext ( ); return ( <div> <div> Products </div> {products.map( ( product ) => { return ( <div> {product.name} + {product.description} </div> )}}; </div> ) }
  • 38. ReactQuery - AppRoot const App: React.FunctionComponent = ( ) => ( <ApplicationContextProvider> <div> <h1> API - React Query </h1> <IncrementButton/> <Products /> <Counter /> </div> </ApplicationContextProvider> ); export default App;
  • 39. State machines: Definition ■ Maths: A finite state machine is a mathematical model of computation that describes the behavior of a system that can be in only one state at any given time ■ Frontend: State machines are a formal and declarative way to model and manage the state of an application. They define all possible finite states that an application can go through. Through events we can transite from one state to the other
  • 40. State machines UI Development Finite State: is like a Behavior which depending on the state behaves different on events i.e. click Play Button State Video Playing State Video Paused click(PlayButton) click(Pause Button) Behavior C State Machine State Video not started Behavior A Behavior B
  • 41. Traditional Event-driven UI Development Init State ■ There is almost infinite set of things that can be done to a UI ■ Each element has a wide range of possible mutations Same state, different values on its UI properties, after triggering events
  • 42. State Machines - Core Concepts ■ Statecharts: Built on top of state machines for more complicated mechanics ■ Actor Model: An actor is an own entity which can have its one state machines or statecharts
  • 43. ■ Not tight to a framework or language ■ Local State first. Use Context for global state ■ XState is a JavaScript/TypeScript implementation of finite state machines and statecharts. It is like useReducer, for local Components state. Could be used globally as well in collaboration with context or useQuery State Machines - Core Concepts
  • 45. XState - ApplicationContext const ApplicationContext = createContext <ApplicationState> ( { frame: 0, thumbnail: ' ', counter: 0, movie: { url: ' ', thumbnail: ' ' }, running: false, onPlay: ( ) => { }, onPause: ( ) => { }, onResume: ( ) => { }, } );
  • 46. XState - useApplicationState const useApplicationState = ( ) : ApplicationState => { const [ state, send ] = useMachine (videoMachine); return { thumbnail: state.context.thumbnail, frame: state.context.frame, counter: state.context.counter, movie: state.context.movie, running: state.value !== "notstarted" && state.value !== "paused" && state.value !== "pausing" onPlay: ( ) => send("PLAY"), onResume: ( ) => send("RESUME"), onPause: ( ) => send("PAUSE"), } ; };
  • 47. XState - ApplicationContextProvider export const ApplicationContextProvider: React.FunctionComponent = ({ children } ) => ( <ApplicationContext.Provider value={useApplicationState( )}> { children } </ApplicationContext.Provider> ); export const useApplicationContext = ( ) => useContext(ApplicationContext);
  • 48. XState - videoMachine const videoMachine = createMachine<VideoContext, VideoContent> ( { id: "video", initial: "notstarted", context: { frame 0, movie: { url: '', thumbnail '', counter 0 } }, states: { notstarted: { on: { PLAY: "started" } }, started: { invoke: { id: "getMovie", src: (context, event)=> fetchMovie(), onDone: { target: "success", } actions: assign({ movie:}), on: { PAUSE: "paused" } }, paused: { on: { RESUME: "resumed" } }, starting: {} }, } )
  • 49. XState - Types import React, { createContext, useContext } from 'react' import { useMachine } from '@xstate/react' import { createMachine, assign } from 'xstate' type VideoEvent = { type: "PLAY" } | { type: "PAUSE" } | { type: "STOP" } | { type: "RESUME" }; type VideoContext = { thumbnail: string; frame: number; counter: number; movie: Movie; }; type Movie = { url: string; thumbnail: string; };
  • 50. XState - LoadingStatus import { useApplicationContext } from './store' const LoadingStatus: React.FunctionComponent = ( ) => { const { running, onPlay, onPause } = useApplicationContext ( ); return ( <div className="my-5"> <button onClick = {running ? onPause : onPlay } > { running ? "Pause" : "Start" } </button> </div> ); };
  • 51. XState - Movie import { useApplicationContext } from './store' const Movie: React.FunctionComponent = ( ) => { const { movie} = useApplicationContext ( ); return movie.url ? ( <> <div>Movie</div> <video> { } </video> </> ) : ( <img src={ movie.thumbnail } /> ); };
  • 52. XState - App import { ApplicationContextProvider } from './store' const App: React.FunctionComponent = ( ) => { <ApplicationContextProvider> <div> <h1> XState</h1> < LoadingState/> < Movie/> </div> </ApplicationContextProvider> }; export default App;
  • 53. Metrics Comparison Table Feature Redux MobX Recoil Ngrx/Store Vuex XState Immutability Enforces immutability through reducers Mutable observables Mutable atom values Enforces immutability through reducers Enforces immutabilit y through mutations Emphasizes immutability through state machines Predictability Actions, Reducers, Centralized Store Reactive programming, Observables Atom-based state management Actions, Reducers, Centralized Store Actions, Mutations, Centralize d Store Finite State Machines, State Charts
  • 54. Metrics Comparison Table Feature Redux MobX Recoil Ngrx/Store Vuex XState Concurrency Limited due to single state tree Good support for concurrency with reactions Limited support for concurrent reactions Supports concurrency through actions Supports concurrency through mutations Built with concurrency in mind Performance Efficient update through Redux's diffing Efficient due to reactive updates Efficient, but depends how atoms are used Efficient with selective memoization Efficient with Vue's reactivity system Emphasizes efficiency in state transitions
  • 55. State Manager Destructuring Fetching - Caching Server state TanStack Query All possible states Fetching fetch/axios/http Framework agnostic pieces State Machines Handling Async Rxjs, Middlewares, Promises Client state Composable atomic units Server-side rendering
  • 56. Future trends for state management ■ Move away from monolithic solutions like Redux to more atomic ones like Recoil, Zustand ■ Emphasis on composability and reusability ■ Emphasis on developer experience ■ Cache friendly ■ Server side state management
  • 58. Data Transformation ■ Change name convention: i.s snake_case them ■ Add new fields for data normalization: key / id ■ Make data type-safe and on the desired shape for runtime because Typescript solves problems during compilation time.
  • 59. Data binding data: [ { id: '1', description: 'test2', image: url ('http://1') }, id: '2', description: 'test2', image: url ('http://2') } ] data.json video.json video: { id: '1', title: 'my video', url: url ('http://1') } Source Code Browser
  • 60. Data binding data: [ { id: '1', description: description item 1, thumbnail: url ('http://1') }, id: '2', description: 'test2', thumbnail: url ('http://2') }] data.json Source Code Browser
  • 61. Data rendering ■ The process of generating visual representation based on input data or instructions ■ Templating (Render Tree Construction) ○ HTML Parsing - Bytes -Tokenization - Nodes ■ DOM Construction ■ CSSOM Construction ■ Layouting ○ Mathematical calculation of the size and position of the nodes ■ Painting ○ Actual positioning of the calculated elements on the screen
  • 62. Concurrency ■ Definition: The ability of a web application to manage and execute multiple tasks simultaneously ○ Rendering user interface ○ Making asynchronous requests ○ Processing user interactions in a non-blocking way ○ Service Workers ○ Error handling
  • 63. Concurrency ■ Key aspects ○ Asynchronous programming ○ Multithreading - Web Workers ○ Event Loop ○ Concurrency control (throttling, debouncing) ○ Service Workers ○ Error handling
  • 64. State: Definition ■ The state is just a snapshot or representation of the system from the client-side at a given point in time ■ It includes things such as: ○ User preferences ○ User input ○ Navigation information ○ Fetched Data from API

Editor's Notes

  1. We used to have the battle of the frameworks, and on top of that we have a new competition which is the battle of state managers. There are state management libraries specific to a framework, while others have implementations in different frameworks. So we have framework-specific and cross-framework state managers. Why all this noise? So much fuss about it? Because they all try to solve problems around a core ingredient of a web application, which is the data. We have clientside-rendered and data-heavy web applications. So it's important to understand how data flow.
  2. On this slide, we have a visual representation of the data flow during data-fetching phase. This is the phase that often refers to the case - As soon as we enter a url - Databases are serving the data - Sometimes we hit proxy servers, for caching for better future retrieval - And before data are display/rendered as pixels in the screen there are some standard sub-processes that always take place a) data transformation b) data-binding c) data-rendering d) data visualisation
  3. Most core web frameworks do not come with an opinionated way of fetching or updating data in a holistic way. Chatgbt Race Condition: If multiple users can update their shopping carts simultaneously, without proper synchronization, it can result in race conditions. For instance, if two users add the same item to their cart simultaneously, the application might struggle to determine the correct quantity or total price. To describe on the 2nd screen that with websockets it will be automatically updated, otherwise the browser needs refresh Problems detected above: - Responsiveness: when we remove the item the UI need immediately to be updated and response to user interaction - Need for consistency and a central store and predictability cause on 2nd screen there is info dependant - Optimization: we can avoid unnecessary http requests if we store data in memory and be accessible in other screens. We can avoid unnecessary re-renders if we carefully manage the state. Redux does it automatically and other libs. Context not, as it dosn't have any state. - Need for predicitasbility - Synchronisatin- Caching: Whatchout: if data need to be updated we will need http request, or polling, or websockets. And then state is updated with most recent data and this update is also reflected in the other parts of the application.useQuery would be a great solution to such problems, as it handles itself all of this syncing logic. It checks if data are stale and if a new request is needed. - Highlight and visualize in the previous design the problems that occur when we handle with data 1. There is need for consistency, otherwise we repeat the avatar name, so duplication of code, extra http request, worst performance 2. As soon as we remove the item, the page needs to be re-rendered and responsive. This can be slow, depending on how we handle updates+reactivity. Additionally this change should be reflected on the other pages where the same component is updated. We can avoid extra http request and use client-side state, if the nature of the data are not often changeable. Predictability: By following specific patterns or techniques, state management ensures that state changes are predictable and can be easily traced or debugged. Reactivity: State management enables the application to react to changes in data and update the user interface accordingly. Consistency: State management ensures that the application’s data remains consistent and up-to-date across different components and modules. Scalability: Proper state management is crucial as it will facilitate the handling of complex data and interactions as the application gets scaled in the future.
  4. Lack of Consistency via a Shared centralized state ((all components have access to a single place and we try to avoid inconsistency) Predictable State Changes (the change you make is expected to be made as such and reflected accordingly to other parts of the application) Performance optimization ((by optimizing state updates and re-rendering). Scalability Testing and debugging Synchronization (handling asynchronous states) Handle both user interactions and asynchronous requests. So orchestrate them better. State management libraries in software development solve several problems related to managing the state of an application. Here are some of the key issues that these libraries address: 1. **Complex State Handling**: Applications often have complex and nested states, such as user interface components, user data, and application settings. State management libraries provide a structured way to define, update, and access this state. 2. **Shared State**: In large applications, multiple components or modules may need access to the same data. State management libraries offer a centralized way to store and share this data, making it easier to keep it consistent and up to date. 3. **Predictable State Changes**: Managing state changes manually can lead to unpredictable behavior and bugs. State management libraries enforce a set of rules and patterns, such as immutability, to ensure that state transitions are predictable and traceable. 4. **Performance Optimization**: Inefficient state management can lead to unnecessary re-renders or updates in a user interface. State management libraries often include optimizations like memoization or diffing algorithms to minimize these performance issues. 5. **Data Flow Control**: Ensuring that data flows in a predictable and unidirectional manner is crucial for maintaining a maintainable and debuggable codebase. State management libraries often encourage a unidirectional data flow, making it easier to understand and debug data changes. 6. **Synchronization**: In applications with asynchronous data updates (e.g., network requests), it's crucial to synchronize state changes and UI updates. State management libraries often provide mechanisms for handling asynchronous operations and updating the state accordingly. 7. **Testing and Debugging**: State management libraries can simplify the process of testing and debugging an application. They often come with tools and patterns for inspecting, mocking, or replaying state changes, making it easier to diagnose and fix issues. 8. **Scalability**: As applications grow in complexity, managing state becomes increasingly challenging. State management libraries offer scalable solutions for handling state in a maintainable way, reducing the risk of introducing bugs as the codebase grows. 9. **Code Organization**: State management libraries often provide a clear structure for organizing state-related code, which can make the codebase more organized and easier to work with, especially in large teams. 10. **Code Reusability**: Many state management libraries allow you to create reusable state containers and reducers, making it easier to share state management logic across different parts of the application. In summary, state management libraries solve problems related to organizing, centralizing, and efficiently handling the state of an application, which can lead to more predictable behavior, better performance, and easier maintenance in complex software projects. bard State management libraries solve a number of problems that developers face when building complex applications, including: Centralized state management: State management libraries provide a central place to store and manage the application state. This makes it easier to keep track of state changes, ensure that all components have access to the latest state, and avoid inconsistencies. Predictable state updates: State management libraries provide a predictable way to update the application state. This helps to prevent errors and unexpected behavior. Performance: State management libraries can improve the performance of applications by optimizing state updates and re-rendering. Scalability: State management libraries can help applications to scale by making it easier to add new features and components without introducing state management problems. Some specific problems that state management libraries solve include: Managing state across multiple components: State management libraries make it easy to share state between different components in an application. This is especially important in large applications with many complex components. Handling asynchronous state updates: State management libraries provide a way to handle asynchronous state updates in a predictable and consistent way. This is essential for applications that need to respond to user interactions and changes in external data sources. Debugging: State management libraries can make it easier to debug applications by providing tools for tracking state changes and identifying the source of problems. Overall, state management libraries can help developers to build more reliable, performant, and scalable applications. Here are some additional benefits of using state management libraries: Improved code readability and maintainability: State management libraries can help to make code more readable and maintainable by separating the state management logic from the component logic. Reduced boilerplate code: State management libraries can help to reduce the amount of boilerplate code that developers need to write, freeing up their time to focus on more important tasks. Increased developer productivity: State management libraries can help to increase developer productivity by providing a set of tools and patterns for managing state effectively.
  5. Codeproject] Lack of Consistency via a Shared centralized state ((all components have access to a single place and we try to avoid inconsistency) Predictable State Changes (the change you make is expected to be made as such and reflected accordingly to other parts of the application) Performance optimization ((by optimizing state updates and re-rendering). Scalability Testing and debugging Synchronization (handling asynchronous states) Handle both user interactions and asynchronous requests. So orchestrate them better. State management libraries in software development solve several problems related to managing the state of an application. Here are some of the key issues that these libraries address: 1. **Complex State Handling**: Applications often have complex and nested states, such as user interface components, user data, and application settings. State management libraries provide a structured way to define, update, and access this state. 2. **Shared State**: In large applications, multiple components or modules may need access to the same data. State management libraries offer a centralized way to store and share this data, making it easier to keep it consistent and up to date. 3. **Predictable State Changes**: Managing state changes manually can lead to unpredictable behavior and bugs. State management libraries enforce a set of rules and patterns, such as immutability, to ensure that state transitions are predictable and traceable. 4. **Performance Optimization**: Inefficient state management can lead to unnecessary re-renders or updates in a user interface. State management libraries often include optimizations like memoization or diffing algorithms to minimize these performance issues. 5. **Data Flow Control**: Ensuring that data flows in a predictable and unidirectional manner is crucial for maintaining a maintainable and debuggable codebase. State management libraries often encourage a unidirectional data flow, making it easier to understand and debug data changes. 6. **Synchronization**: In applications with asynchronous data updates (e.g., network requests), it's crucial to synchronize state changes and UI updates. State management libraries often provide mechanisms for handling asynchronous operations and updating the state accordingly. 7. **Testing and Debugging**: State management libraries can simplify the process of testing and debugging an application. They often come with tools and patterns for inspecting, mocking, or replaying state changes, making it easier to diagnose and fix issues. 8. **Scalability**: As applications grow in complexity, managing state becomes increasingly challenging. State management libraries offer scalable solutions for handling state in a maintainable way, reducing the risk of introducing bugs as the codebase grows. 9. **Code Organization**: State management libraries often provide a clear structure for organizing state-related code, which can make the codebase more organized and easier to work with, especially in large teams. 10. **Code Reusability**: Many state management libraries allow you to create reusable state containers and reducers, making it easier to share state management logic across different parts of the application. In summary, state management libraries solve problems related to organizing, centralizing, and efficiently handling the state of an application, which can lead to more predictable behavior, better performance, and easier maintenance in complex software projects. bard State management libraries solve a number of problems that developers face when building complex applications, including: Centralized state management: State management libraries provide a central place to store and manage the application state. This makes it easier to keep track of state changes, ensure that all components have access to the latest state, and avoid inconsistencies. Predictable state updates: State management libraries provide a predictable way to update the application state. This helps to prevent errors and unexpected behavior. Performance: State management libraries can improve the performance of applications by optimizing state updates and re-rendering. Scalability: State management libraries can help applications to scale by making it easier to add new features and components without introducing state management problems. Some specific problems that state management libraries solve include: Managing state across multiple components: State management libraries make it easy to share state between different components in an application. This is especially important in large applications with many complex components. Handling asynchronous state updates: State management libraries provide a way to handle asynchronous state updates in a predictable and consistent way. This is essential for applications that need to respond to user interactions and changes in external data sources. Debugging: State management libraries can make it easier to debug applications by providing tools for tracking state changes and identifying the source of problems. Overall, state management libraries can help developers to build more reliable, performant, and scalable applications. Here are some additional benefits of using state management libraries: Improved code readability and maintainability: State management libraries can help to make code more readable and maintainable by separating the state management logic from the component logic. Reduced boilerplate code: State management libraries can help to reduce the amount of boilerplate code that developers need to write, freeing up their time to focus on more important tasks. Increased developer productivity: State management libraries can help to increase developer productivity by providing a set of tools and patterns for managing state effectively.
  6. A state management library will be helpful to get the following things done: Model your application state Derive computed values from it Monitor it for changes
  7. It encapsulates different types of state: - Ui state: for controlling interactive parts of our application like modals, or theme - Server-caching state we call some api, cache response and use it (i.e. swr) in the early days of just fetching api, using result. Components dispatch actions to store Reducers act upon actions and mutate store Store sends update down to components
  8. https://mobx.js.org/README.html Observables are just functions that throw values, and objects know as observers subscribe to these values There is no need to manually optimize components with error-prone and sub-optimal techniques like memoization and selectors. All you do is a bunch of values and you just grab them as observables values. that means when it updates, everything that depends on it is updated. if we mutate this value, no need to dispatch and action. This mutation cause mutations everywhere. It's more smart comparable to how you would do it yourself. mobx is still predictable, but it's not super predictable as redux
  9. You store info in an atom. You set value, You can get value from atoms. You can connect atoms. Atomic State Management involves utilizing Atoms as a central repository for state management. It can be seen as an upgraded version of the useState hook, allowing for state sharing between components. This approach combines the benefits of both component state and global store patterns Atoms are used as single source of state, Nice loose coupling. Why to use that? If you like loose coupling but don't want to use RXJS Jotai is event better, can be connected with XState
  10. https://www.wednesday.is/writing-articles/react-query-the-what-how-when React Query complements these libraries and helps create a separation of concerns. In most client-side applications, they deal with the server state. https://tanstack.com/query/v4/docs/react/guides/query-invalidation Waiting for queries to become stale before they are fetched again doesn't always work, especially when you know for a fact that a query's data is out of date because of something the user has done. For that purpose, the QueryClient has an invalidateQueries method that lets you intelligently mark queries as stale and potentially refetch them too
  11. Is it the newest kid on the block? It's a hyped library? https://podcasts.apple.com/lu/podcast/from-redux-to-xstate-with-david-khourshid/id1546641347?i=1000520331521 It's a great implementation of state machines and statecharts and actors. In other libraries we mostly think about WHERE we store data. We discuss how these data changes over time and how it can't change. We separate that by state machines. finit state is like a behavior which depending on the state behaves different on events. it's all about separating behaviors of your application state and transitioning between them State machines is a collection of states, events and transitions between states. Statecharts are built on top of statemachines for more nested/parallel and a lot of other mechanisms that let state machines scale. The actor model builds on top of them, where an actor is an entity where inside has its own state machine or statechart. An actor can talk to other actors. The question of should I use it or not is not correct. Is about should I make it implicit or explicit? Benefits: Beeing able to know everything that happened and that can happen. In Redux time-travelling debugging,here we go one step further, Cause we can draw what can happen, all possible scenarios. It's also a visual language in a graph (lines between events and states): that can help product managers, designers and different developers Benefits: You have to handle all the states, You need to be explicitly, you need to know all the states, while in other cases you handle the states you are aware of. An example where this could work is react query with strict typing. This is like a simpler version of how state machine works. We overestimate ourselves that we know what can happen.We see buggy applications:- where the loading spinner keeps showing: why? internet connection time out? How Xstate relates to Redux? Which parts of Redux can be replaced by XState? Redux: Is single global atomic. It's global first. You cannot use it locally. Xstate is local-first, which means to replace useReducer and useSate at the component Level. The mechanics are very similar: - Redux is about dispatching actions, XState about sending events useEffects in Redux are afterthoughts, you need to handle them with middleware side effects in xState are pickedIn the machine Model, so their outputs can be thought of as side effects/actions. You don't need necessarily XState to implement state machines, you can also use Redux. But needs a lot of discipline. State machines have nothing to do with any framework and language at all. XState has a few hooks: - useMachine, which essentially a replacement of useReducer. It can spawn actors, it can have sideEffects - regarding usingContext, you can use useInterpret, lets you put in the machine in there, gets instance of the machine (like a subscribe object) and once you pass that to context you can useService to pass to any component actors to communicate with different state machines, and we delegate some tasks that are outside state machine. FiniteMachines https://kyleshevlin.com/guidelines-for-state-machines-and-xstate A state machine, more specifically a finite state machine, is a means of representing all the possible enumerated states of a system and the possible enumerated transitions between states in that system.
  12. https://statecharts.dev/use-case-statecharts-in-user-interfaces.html (traditiona event driven interfaces) In a traditional event driven user interface component, say, the ubiquitous HTML <input> element, the UI component generates a lot of events, that the developer can subscribe to, from gaining or losing focus, editing, selecting, mouse movement and so on. A developer has a plethora of events to choose between. There is a similar almost infinite set of things that can be done to a user interface. Each element has a wide range of possible mutations. It is up to the developer to decide what to do based on whatever event that happens. In other libraries we mostly think about WHERE we store data. We discuss how these data changes over time and how it can't change. By state machines we separate that. finit state is like a behavior which depending on the state behaves different on events. it's all about separating behaviors of your application state and transitioning between them State machines is a collection of states, events and transitions between states. Statecharts are built on top of statemachines for more nested/parallel and a lot of other mechanisms that let state machines scale. The actor model builds on top of them, where an actor is an entity where inside has its own state machine or statechart. An actor can talk to other actors. The question of should I use it or not is not correct. Is about should I make it implicit or explicit? Benefits: Beeing able to know everything that happened and that can happen. In Redux time-travelling debugging,here we go one step further, Cause we can draw what can happen, all possible scenarios. It's also a visual language in a graph (lines between events and states): that can help product managers, designers and different developers Benefits: You have to handle all the states, You need to be explicitly, you need to know all the states, while in other cases you handle the states you are aware of. An example where this could work is react query with strict typing. This is like a simpler version of how state machine works. We overestimate ourselves that we know what can happen. We see buggy applications:- where the loading spinner keeps showing: why? internet connection time out? How Xstate relates to Redux? Which parts of Redux can be replaced by XState? Redux: Is single global atomic. It's global first. You cannot use it locally. Xstate is local-first, which means to replace useReducer and useSate at the component Level. The mechanics are very similar: - Redux is about dispatching actions, XState about sending events
  13. https://statecharts.dev/use-case-statecharts-in-user-interfaces.html (traditiona event driven interfaces) In a traditional event driven user interface component, say, the ubiquitous HTML <input> element, the UI component generates a lot of events, that the developer can subscribe to, from gaining or losing focus, editing, selecting, mouse movement and so on. A developer has a plethora of events to choose between. There is a similar almost infinite set of things that can be done to a user interface. Each element has a wide range of possible mutations. It is up to the developer to decide what to do based on whatever event that happens. In other libraries we mostly think about WHERE we store data. We discuss how these data changes over time and how it can't change. By state machines we separate that. finit state is like a behavior which depending on the state behaves different on events. it's all about separating behaviors of your application state and transitioning between them State machines is a collection of states, events and transitions between states. Statecharts are built on top of statemachines for more nested/parallel and a lot of other mechanisms that let state machines scale. The actor model builds on top of them, where an actor is an entity where inside has its own state machine or statechart. An actor can talk to other actors. The question of should I use it or not is not correct. Is about should I make it implicit or explicit? Benefits: Beeing able to know everything that happened and that can happen. In Redux time-travelling debugging,here we go one step further, Cause we can draw what can happen, all possible scenarios. It's also a visual language in a graph (lines between events and states): that can help product managers, designers and different developers Benefits: You have to handle all the states, You need to be explicitly, you need to know all the states, while in other cases you handle the states you are aware of. An example where this could work is react query with strict typing. This is like a simpler version of how state machine works. We overestimate ourselves that we know what can happen. We see buggy applications:- where the loading spinner keeps showing: why? internet connection time out? How Xstate relates to Redux? Which parts of Redux can be replaced by XState? Redux: Is single global atomic. It's global first. You cannot use it locally. Xstate is local-first, which means to replace useReducer and useSate at the component Level. The mechanics are very similar: - Redux is about dispatching actions, XState about sending events
  14. https://codesandbox.io/s/react-query-observables-2h9tw?file=/src/App.tsx:212-235 react query with observables
  15. https://javascript.plainenglish.io/why-i-think-parsing-and-transforming-api-response-data-in-the-front-end-is-necessary-7ae9e832f0d
  16. DEFINITION Data binding is a connector between user interface and business logic, between destination and source. How data are binded in the UI When a javascript variable displays some value in the HTML
  17. DEFINITION How data are binded in the UI When a javascript variable displays some value in the HTML
  18. https://medium.com/codex/tangled-with-front-end-state-management-use-the-store-86632c20f2ef https://medium.com/codex/tangled-with-front-end-state-management-use-the-store-86632c20f2ef