# Concurrent React, Redux and State Management
## Concurrent React
### Time Slicing
- Prevent blocking
```
* setState
* start render
* render yield
|
| * some other event handler
|
* render continue
* render yield
|
| * some other event handler
|
* render continue
* render finish
```
- Prioritized reconciling
```
* (low priority event)
|
* setState
* start render
* render yield
|
| * (high priority event)
| |
| * setState
| * render start
| |
| * finish render
|
* re-apply state change
* render
```
### Suspense
- Throwing Promises
- Placeholders
- `maxDuration`
```
* (event)
|
* setState
* start render
* render throw promise
.
.
. * (event)
. |
. * setState
. * render start
. * finish render
.
.
.
.
* promise resolve
* re-aplly state change
* render
```
## Consequences
- React is in charge of state
- Ensures consistent state for tree
across time slices (no "tearing")
- "Work in progress" state
## Redux
- v5: Strore via Context
- v6: State (and Store) via Context
- Push vs Pull
```
| REDUX STORE
|
* (low priority event) | { users: [] }
| |
* dispatch |
* store change | { users: [a,b,c] }
* Provider#setState |
* render start |
* render yield |
| |
| * (high priority event) |
| | |
| * dispatch |
| * store change | { expanded: true, users: [a,b,c] }
| * Provider#setState |
| * render start |
| | |
x | cancel render |
| |
* finish render |
```
Component State > Global State
## Caching External Data
- Prevent re-fetching data
- Take advantage of concurrent rendering mode
- Prevent tearing
### Component State?
- Data lost on unmount
- Does not work with suspense
### Global Singleton?
- Risk of tearing
### `Context.write`
https://github.com/reactjs/rfcs/pull/89
React managed state outside the component tree
```
const Context = React.createContext(defaultValue);
function Component() {
return (
{value => /* render something ... */}
);
}
```
```
const Context = React.createContext(initialValue, contextDidUpdate);
Context.write(newValue);
Context.write(prevValue => newValue);
```
```
const Store = React.createContext(initialState);
export function dispatch(action) {
Store.write(state => reducer(state, action));
}
export function useStore() {
return useContext(Store);
}
```
```
| Context
|
* (low priority event) | * { users: [] }
| | |
* dispatch | |\
* Context.write | * \ { users: [a,b,c] }
* render start | | \
* render yield | | |
| | | |
| * (high priority event) | | |
| | | | |
| * dispatch | | |
| * Context.write | | * { expanded: true, users: [] }
| * render start | | /
| * finish render | | /
* | |/
* re-apply state changes | * { expanded: true, users: [a,b,c] }
* render
```
Dependency Injection/Testing
```
```
## Let Others Take Care of It
- React Apollo
- Unstated
- Relay?
## Thanks!
github.com/tf
@tfischbach
www.codevise.de
## References
https://www.youtube.com/watch?v=nLF0n9SACd4
https://blog.isquaredsoftware.com/2018/11/react-redux-history-implementation/
https://github.com/reduxjs/react-redux/issues/890
https://github.com/reduxjs/react-redux/pull/1000
https://github.com/reactjs/rfcs/pull/89