Gergel Gorvat
Volodymyr Vyshko
JS Community
JS Community
Intro
Why you should use Redux
Why you shouldn't
JavaScript community
In general
User
Scene
Router
State
State
Allocated objects
All the variables
File descriptors
Network sockets
It is basically all of the information that represents what is currently happening in the application.
What is your opinion?
How data gets into/out of a store
How business logic interacts with the UI
Application architecture
How information flows through a system
Data persistence
Programming paradigms
networking and caching
Presentation behavior
You have reasonable amounts of data changing over time
Many people working on the project, you want a consistent way to work with state
You don't want to reinvent the wheel again by your own
You want to use some extensions for easier debugging
56.4k
No.
Hi, I'm a Redux maintainer.
No, Context does not replace Redux, although there is some overlap. And yes, Redux will continue to be very relevant and useful for a long time. It's currently used by 50% of React apps, and lots of folks are continuing to learn it on a daily basis.
Mark Erikson
Consistent architectural pattern
Debugging capabilities
Middleware
Addons and extensibility
Cross-platform and cross-framework usage
Better performance than Conext
Still good in many cases
Not a silver bullet, but
Boilerplate problem
Boilerplate problem
Boilerplate problem
Boilerplate problem
Boilerplate problem
Boilerplate problem
const types = {
INCREMENT: 'counter/redux/increment',
DECREMENT: 'counter/redux/decrement',
RESET: 'counter/redux/reset',
SET_STEP: 'counter/redux/setStep',
};
export default types;
import types from './types';
export const setStep = (payload) => ({
type: types.SET_STEP,
payload,
});
export const increment = (payload) => ({
type: types.INCREMENT,
payload,
});
export const decrement = (payload) => ({
type: types.DECREMENT,
payload,
});
export const reset = () => ({
type: types.RESET,
});
import { combineReducers } from 'redux';
import types from './types';
const initialState = {
step: 10,
value: 0,
};
const step = (state = initialState.step, action) => {
switch (action.type) {
case types.SET_STEP:
return action.payload;
default:
return state;
}
};
const value = (state = initialState.value, action) => {
switch (action.type) {
case types.INCREMENT:
return state + action.payload;
case types.DECREMENT:
return state - action.payload;
case types.RESET:
return initialState.value;
default:
return state;
}
};
export default combineReducers({ step, value });
https://redux-toolkit.js.org
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
step: 10,
value: 0,
};
export const counterSlice = createSlice({
name: 'counter/toolkit',
initialState,
reducers: {
increment: (state, action) => {
state.value += action.payload;
},
decrement: (state, action) => {
state.value -= action.payload;
},
setStep: (state, action) => {
state.step = action.payload;
},
},
});
export const {
increment,
decrement,
setStep
} = counterSlice.actions;
export default counterSlice.reducer;
thunk / createAsyncThunk
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { userAPI } from './userAPI'
// First, create the thunk action
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
// Then, handle actions in your reducers:
const usersSlice = createSlice({
name: 'users',
initialState: { entities: [], loading: 'idle' },
reducers: {
// standard reducer logic, with auto-generated action types per reducer
},
extraReducers: (builder) => {
// Add reducers for additional action types here, and handle loading state as needed
builder.addCase(fetchUserById.fulfilled, (state, action) => {
// Add user to the state array
state.entities.push(action.payload)
})
},
})
// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123)
- pending: 'users/requestStatus/pending'
- fulfilled: 'users/requestStatus/fulfilled'
- rejected: 'users/requestStatus/rejected'
store.js
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './rootReducer';
const composeEnhancers =
(process.env.NODE_ENV === 'development' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
compose;
const middleware = [thunk];
export const store = createStore(
reducer,
/* preloadedState, */
composeEnhancers(applyMiddleware(...middleware)),
);
import { configureStore } from '@reduxjs/toolkit';
import reducer from './rootReducer';
export const store = configureStore({
reducer,
devTools: process.env.NODE_ENV === 'development', // true by default
});
function mapStateToProps(state) {
return {
aRandomProp: Math.random()
}
}
function mapStateToProps(state) {
return {
aFilteredArray: state.anArray.filter(value => value.isTrue === true)
}
}
Use selectors, memoization and global state instead
Container
Container
Container
Component
Container
1..N
1..N
Component
Component
Component
const state = {
users: [{ ... }],
selectedUser: {
id: 1,
name: 'Alyosha',
start: startTime,
end: endTime
},
numberOfUsers: 10,
}
Often we have a piece of the state which can be computed from another
React state
Redux
(link)
Redux doesn't solve any problem. It just creates a new problem by giving you an abstract box. And what to store is that box - its your problem.
Dan Abramov
An antipattern is just like a pattern, except that instead of a solution it gives something that looks superficially like a solution but isn't one.
Andrew Koenig (C Traps and Pitfalls)
No encapsulation
Different lifecycle
Global store is a singleton
variables visible to all the other components, even components that don’t need to know about this prop
We must manually keep cleaning the store from garbage of old components that already left the screen
but a component may have many instances, singletons are most of the time considered an anti-pattern
Don't use Redux if you wasting much CPU time or RAM resources on maintaining the immutability
Don't use redux if your application using it mainly for caching fetched resources
Don't use redux if your app mainly consists of complex forms
Don't use Redux if your containers are mostly independent
October 2019
October 2020
25%
50%
75%
100%
25%
Learning curve
Boilerplate code
Performance
Central store
No built-in way to handle side-effects
State of JS 2020
Is it dead ?
Use react features/hooks instead ?
You need a single source of truth
You want to maintain an undo history
You need a serializable state/actions
Travel between the state history in development
Provide alternative UI without disturbing too much of the business logic
Otherwise...
Built-in features into your view lib/framework
Apollo
Relay
MobX
Redux
MST
JS Community
JS Community
Join http://kahoot.it/ or use the QR code!
JS Community