Understanding Redux: Core Concepts, Principles, and React‑Redux Integration

This article explains Redux’s simple yet powerful state‑management model, its three core principles, key concepts such as actions, reducers, and store, and demonstrates how to integrate Redux with React using react‑redux’s Provider and connect APIs with practical code examples.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Understanding Redux: Core Concepts, Principles, and React‑Redux Integration

Overview

Redux itself is an extremely simple state‑management framework; its simplicity comes from having few concepts and a clear process. However, because it imposes no strict constraints, misuse can make state management more chaotic.

To use Redux well, you must first understand its basic concepts—not just read the docs, but grasp their definitions and how they relate to overall state management. Then map these concepts onto concrete business systems to plan the application’s state management.

Redux Core and Principles

The core purpose of Redux can be summed up in one sentence: clearly describe the application’s state. The Redux API provides tools to achieve this, but the same state management could be implemented without them.

The three principles Redux proposes are not enforced by the framework; the framework is free to organize code however you like. These principles should be kept in mind when you design your own state‑management solution.

这个应用的状态是一个唯一的状态树</code><code>状态是只读的, 只能通过 action 来触发修改, 其实实际修改状态的是 reducer</code><code>修改状态只能通过纯函数

Concepts in Redux

Understanding the basic concepts helps you organize a Redux‑style state management; merely using the Redux API does not constitute true Redux. The main concepts are Action, Reducer, and Store.

在redux中分为3个对象:Action、Reducer、Store

All other concepts derive from these three and are closely related to Redux’s state‑handling flow.

Data Flow

Strict unidirectional data flow is the foundation of Redux.

Unidirectional flow makes each state change explicit, ensuring the application’s state changes are clear and traceable.

Reducer

A reducer is the function that actually changes the state; in Redux only reducers can modify state, and they must be pure functions.

According to the principles, the whole application has a single unique state tree, so theoretically one reducer would suffice. In practice, larger applications split reducers across modules for better collaboration and maintainability.

Reducers are usually organized by module or framework and can be combined into a single state tree using Redux’s combineReducers API.

When using reducers, keep two points in mind:

必须是纯函数</code><code>多个 reducer 文件时, 确保每个 reducer 处理不同的 action, 否则可能会出现后面的 reducer 被覆盖的情况

State

The state (or store) represents the entire application’s data. Deciding what belongs in state, what does not, and what should be managed locally is crucial; good state definition directly impacts maintainability and scalability, regardless of the chosen framework.

Many applications adopt advanced state‑management frameworks but neglect proper state definition; a poorly defined state cannot be effectively managed.

State‑management frameworks often provide computed properties; Redux also supports them in two ways:

通过 reducer, 定义一些计算属性(本质上还是 <span>state</span>), 在改变 <span>state</span> 的时候同时修改这些计算属性.</code><code>通过 selector, 这个是专门用于 redux 库的 selector. reselect

The second method is more generic and is used in the examples that follow.

Installation

npm i -S redux react-redux redux-devtools

Action

对行为(如用户行为)的抽象</code><code>Action 就是一个普通 JavaScript 对象。如:{ type: 'ADD_TODO', text: 'Go to swimming pool' }(其中 type 字段是约定也是必须的)</code><code>作为 Reducer 的参数

Redux Example

import { createStore } from 'redux'</code><code>// reducer</code><code>function counter(state = 0, action) {</code><code>    switch (action.type) {</code><code>        case 'INCREMENT':</code><code>            return state + 1</code><code>        default:</code><code>            return state</code><code>    }</code><code>}</code><code>// state</code><code>let store = createStore(counter); // 会调用</code><code>// 监听</code><code>store.subscribe(() =></code><code>    console.log(store.getState())</code><code>);</code><code>// 调用reducer</code><code>store.dispatch({ type: 'INCREMENT' });

react‑redux

React’s requirements:

数据总是单向从顶层向下分发的</code><code>组件之间的沟通通过提升state:子组件改变父组件state的办法只能是通过onClick触发父组件声明好的回调</code><code>state越来越复杂:单页应用的发展导致。包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

react‑redux divides components into two types: presentational components and container components.

Presentational Component

数据来源:props</code><code>数据修改:通过props的回调函数</code><code>不直接使用redux

Container Component

数据来源:redux state</code><code>数据修改:redux 派发action</code><code>直接使用redux

react‑redux provides two main APIs: Provider and connect .

Provider

<Provider store>
在原应用组件上包裹一层,使原来整个应用成为Provider的子组件</code><code>接收Redux的store作为props,内部通过context对象传递给子孙组件上的connect

connect

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)

connect links a React component to the Redux store. mapStateToProps(state, ownProps) : stateProps maps store data to component props and is called whenever state or ownProps change.

将 store 中的数据作为 props 绑定到组件上。</code><code>当 state 变化,或者 ownProps 变化的时候,mapStateToProps 都会被调用,计算出一个新的 stateProps
mapDispatchToProps(dispatch, ownProps): dispatchProps

binds dispatch functions to props; mergeProps defines how stateProps and dispatchProps are merged (default is Object.assign).

mapDispatchToProps(dispatch, ownProps): dispatchProps:将 dispatch(action) 作为 props 绑定到组件上</code><code>mergeProps:指定 stateProps 以及 dispatchProps 合并到 ownProps 的方式。(默认使用Object.assign)

connect is a higher‑order component (HOC). Simplified source:

export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {</code><code>  return function wrapWithConnect(WrappedComponent) {</code><code>    class Connect extends Component {</code><code>        constructor(props, context) {</code><code>            this.store = props.store || context.store</code><code>            this.stateProps = computeStateProps(this.store, props)</code><code>            this.dispatchProps = computeDispatchProps(this.store, props)</code><code>            this.state = { storeState: null }</code><code>            // 合并stateProps、dispatchProps、parentProps</code><code>            this.updateState()</code><code>        }</code><code>        shouldComponentUpdate(nextProps, nextState) {</code><code>            // 进行判断,当数据发生改变时,Component重新渲染</code><code>            if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {</code><code>                this.updateState(nextProps)</code><code>                return true</code><code>            }</code><code>        }</code><code>        componentDidMount() {</code><code>            this.store.subscribe( () => this.setState({ storeState: this.store.getState() }) )</code><code>        }</code><code>        render() {</code><code>            return (</code><code>                <WrappedComponent {...this.nextState} /></code><code>            )</code><code>        }</code><code>      }</code><code>      return Connect;</code><code>    }</code><code>}

react‑redux Example: Counter.js

import React, { Component } from 'react';</code><code>import { createStore, bindActionCreators } from 'redux';</code><code>import { Provider, connect } from 'react-redux';</code><code></code><code>function clickReduce(state = { todo: 1 }, action) {</code><code>    switch (action.type) {</code><code>        case 'click':</code><code>            return Object.assign({}, state, { todo: state.todo + 1 });</code><code>        default:</code><code>            return state;</code><code>    }</code><code>}</code><code></code><code>let store = createStore(clickReduce);</code><code></code><code>class Counter extends Component {</code><code>    render() {</code><code>        return (</code><code>            <div></code><code>                <div>{this.props.todo}</div></code><code>                <button onClick={this.props.clickTodo}>Click</button></code><code>            </div></code><code>        )</code><code>    }</code><code>}</code><code></code><code>// 方式1:</code><code>export default connect(state => ({ todo: state.todo }),</code><code>    dispatch => ({ clickTodo: () => dispatch({ type: 'click' }) }))(Counter)</code><code></code><code>// 方式2:</code><code>export default connect(state => ({ todo: state.todo }),</code><code>    dispatch => bindActionCreators({ clickTodo: () => ({ type: 'click' }) }, dispatch));

index.js

import React, { Component } from 'react';</code><code>import { Provider } from 'react-redux';</code><code>import { render } from 'react-dom';</code><code>import Clock from './Clock'</code><code></code><code>render((</code><code><Provider store={store}></code><code>    <Counter /></code><code></Provider>), root);

In Redux you can only dispatch simple action objects, and in react‑redux you can only define synchronous reducer methods. The next section will introduce how to define asynchronous methods in react‑redux for production use.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptReduxState ManagementReact-Redux
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.