Redux
Redux is a predictable state container for JavaScript applications, often used with React but applicable to any other framework or vanilla JavaScript. It helps manage the state of your application in a single, centralized location. This approach makes it easier to understand how your application state changes over time and debug complex interactions within your app.
Redux 是 React 最常用的集中狀態管理工具,類似於 Vue 中的 Pinia (Vuex), 可以獨立於框架運行。
Core Concepts
Redux is built around three fundamental principles:
Single Source of Truth
The state of your entire application is stored in an object tree within a single store. This makes it easy to create universal apps, as the state from your server can be serialized and hydrated into the client with no extra coding effort.
State is Read-Only
The only way to change the state is to emit an action, an object describing what happened. This ensures that neither the views nor the network callbacks will ever write directly to the state. Instead, they express an intent to transform the state.
Changes are Made with Pure Functions
To specify how the state tree is transformed by actions, you write pure reducers. Reducers are pure functions that take the previous state and an action, and return the next state.
Basic Elements
Actions
Actions are plain JavaScript objects that have a type
field. You can think of an action as an event that describes something that happened in the application.
const addTodoAction = {
type: 'todos/todoAdded',
payload: 'Buy milk',
};
Reducers
A reducer is a function that receives the current state and an action object, decides how to update the state if necessary, and returns the new state: (state, action) => newState
. You can break down the root reducer into smaller reducers independently operating on the different parts of the state tree.
function todosReducer(state = [], action) {
switch (action.type) {
case 'todos/todoAdded':
return [...state, action.payload];
default:
return state;
}
}
Store
The store brings actions and reducers together. It holds the application state, allows access to state via getState()
, allows state to be updated via dispatch(action)
, and registers listeners via subscribe(listener)
.
import { createStore } from 'redux';
let store = createStore(todosReducer);
Why Use Redux?
- Predictability of outcome: There is always one source of truth, the state object.
- Maintainability: Having a predictable outcome and strict structure makes the code easier to maintain.
- Server-side rendering: You can preload on the server, send it to the client, and boot up from where you left off.
- Developer tools: You can track everything from actions to state changes.
- Community and ecosystem: There are loads of resources, middleware, and tools built around Redux.
Conclusion
Redux provides a solid, stable, and mature solution to manage state in your JavaScript application. It enforces a unidirectional data flow and leverages pure functions for updating the application's state, leading to more predictable and easier to understand code. While it introduces certain concepts and boilerplate, the clarity and stability it brings to complex applications can be invaluable.
For further learning, the official Redux documentation is an excellent resource.
Redux Toolkit and React-Redux are part of the Redux ecosystem, which is a popular library for managing application state in JavaScript apps, especially in React applications. They serve different purposes but are often used together to simplify state management and make the developer's life easier.
Redux Toolkit
Redux Toolkit is the official, opinionated, batteries-included toolset for efficient Redux development. It's intended to be the standard way to write Redux logic. It was created to address the common concerns of Redux's verbosity and complexity by providing a simplified API and set of tools. Key features and benefits include:
- Simplifies store setup: Offers a simplified configuration option for setting up the store with good defaults.
createSlice
function: Simplifies the process of writing action creators and reducers. A slice is a collection of reducer logic and actions for a single feature of your app, essentially reducing the boilerplate code.createAsyncThunk
: Simplifies handling asynchronous actions without the need for middleware like redux-thunk, by automatically generating action creators and handling pending, fulfilled, and rejected action types.- Immutability and update logic: Integrates with Immer, allowing you to write simpler immutable update logic by using standard mutable code (like assignments and pushes).
- DevTools extension integration: Comes configured out of the box to work with the Redux DevTools Extension, offering a rich set of tools for debugging.
React-Redux
React-Redux is the official React binding for Redux. It allows React components to read data from a Redux store, and dispatch actions to the store to update data. React-Redux is necessary for integrating Redux into a React application, as it provides the Provider
component and the useSelector
and useDispatch
hooks. Key features and benefits include:
Provider
component: Makes the Redux store available to any nested components that need to access the Redux store.useSelector
hook: Allows you to extract data from the Redux store state, using a selector function.useDispatch
hook: Gives you access to the Redux store'sdispatch
function to dispatch actions.- Performance optimizations: React-Redux implements several performance optimizations internally, so your React components only re-render when the data they need from the Redux store has changed.
Usage Together
In a typical React application using Redux for state management, you would use React-Redux to connect your React components to the Redux store. Redux Toolkit would be used to simplify the creation and management of the Redux store, reducers, and actions. This combination provides a powerful, efficient, and easy-to-understand approach to managing global state in a React application.
Asynchronous redux
- 創建 store 的寫法保持不變, 配置好同步修改狀態的方法。
- 單獨封裝一個函數,在函數內部 return 一個新函數,在函數中。 2.1 封裝異步請求獲取數據。 2.2 調用同步 actionCreator 傳人異步數據生成一個 action 對象,並使用 dispatch 提交
- 組件中 dispatch 的寫法保持不變。