Redux 完整基础操作(原生 Redux,不结合 React-Redux)

一、Redux 三大核心概念

  1. Store:唯一数据源,整个应用只有一个 store,存放所有状态
  2. State:仓库里的数据,只读,不能直接修改
  3. Action :描述「要做什么」的普通对象,必须带 type 属性(操作标识)
  4. Reducer:纯函数,接收旧 state + action,返回新 state,唯一能改状态的地方

数据流:View 触发 dispatch(action) → Reducer 计算新 state → Store 更新 → View 更新

二、基础安装

bash

运行

bash 复制代码
# 原生redux
npm install redux
# react项目配套
npm install redux react-redux

三、最简原生 Redux 完整示例(纯 JS)

1. 导入 createStore 创建仓库

js

javascript 复制代码
import { createStore } from 'redux'

2. 定义初始 state

js

csharp 复制代码
// 初始状态
const initState = {
  count: 0,
  user: { name: '' }
}

3. 编写 reducer 纯函数

规则:

  • 不能修改原 state,必须返回全新对象
  • 不能异步、定时器、随机数等副作用
  • 参数:(state, action) => newState

js

php 复制代码
function reducer(state = initState, action) {
  switch (action.type) {
    case 'ADD':
      // 返回新state,不能直接改state.count++
      return {
        ...state,
        count: state.count + 1
      }
    case 'SUB':
      return {
        ...state,
        count: state.count - 1
      }
    case 'SET_NAME':
      return {
        ...state,
        user: {
          ...state.user,
          name: action.payload
        }
      }
    default:
      // 无匹配action返回原state
      return state
  }
}

4. 创建 store

js

ini 复制代码
const store = createStore(reducer)

5. 四大基础 API(核心操作)

① store.getState () 获取当前所有状态

js

css 复制代码
console.log(store.getState())
// { count:0, user:{name:''} }

② store.dispatch (action) 派发动作,修改状态

action 是对象,type 必传,payload 存放传递的数据

js

php 复制代码
// 数字+1
store.dispatch({ type: 'ADD' })
// 数字-1
store.dispatch({ type: 'SUB' })
// 传入参数 payload
store.dispatch({ type: 'SET_NAME', payload: '张三' })

③ store.subscribe (回调) 监听 state 变化

state 更新就执行回调,常用于页面刷新

js

javascript 复制代码
const unSubscribe = store.subscribe(() => {
  console.log('状态更新了:', store.getState())
})

// 取消监听
unSubscribe()

④ 完整测试流程

js

php 复制代码
// 监听
store.subscribe(() => {
  console.log(store.getState())
})

// 派发action修改数据
store.dispatch({ type: 'ADD' })
store.dispatch({ type: 'ADD' })
store.dispatch({ type: 'SET_NAME', payload: '李四' })

四、规范封装 Action Creator(工厂函数)

手写 {type:xxx} 重复,封装函数生成 action

js

go 复制代码
// action创建函数
const add = () => ({ type: 'ADD' })
const sub = () => ({ type: 'SUB' })
const setName = (name) => ({
  type: 'SET_NAME',
  payload: name
})

// 使用
store.dispatch(add())
store.dispatch(setName('老王'))

五、React 中使用:react-redux 基础

1. 顶层 Provider 注入 store

入口文件 main.js

js

javascript 复制代码
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from './reducer'
import App from './App'

const store = createStore(reducer)

ReactDOM.createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    <App />
  </Provider>
)

2. 函数组件:useSelector + useDispatch(hooks 推荐)

jsx

javascript 复制代码
import { useSelector, useDispatch } from 'react-redux'
import { add, setName } from './action'

export default function Counter() {
  // 读取state,自动订阅更新
  const { count, user } = useSelector(state => state)
  // 获取dispatch方法
  const dispatch = useDispatch()

  return (
    <div>
      <p>数字:{count}</p>
      <p>姓名:{user.name}</p>
      <button onClick={() => dispatch(add())}>+1</button>
      <button onClick={() => dispatch(setName('小红'))}>改名</button>
    </div>
  )
}

3. 类组件 connect(老写法)

jsx

javascript 复制代码
import { connect } from 'react-redux'

function App({ count, add }) {
  return <button onClick={add}>{count}</button>
}

// mapStateToProps:把state映射为props
const mapState = state => ({
  count: state.count
})
// mapDispatchToProps:把dispatch映射为props
const mapDispatch = { add }

export default connect(mapState, mapDispatch)(App)

六、拆分多模块 state(combineReducers)

项目大时拆分多个 reducer,合并成根 reducer

js

php 复制代码
import { createStore, combineReducers } from 'redux'

// 计数器模块reducer
function countReducer(state = { num: 0 }, action) {
  switch (action.type) {
    case 'ADD': return { num: state.num + 1 }
    default: return state
  }
}

// 用户模块reducer
function userReducer(state = { name: '' }, action) {
  switch (action.type) {
    case 'SET_USER': return { name: action.payload }
    default: return state
  }
}

// 合并reducer
const rootReducer = combineReducers({
  count: countReducer,
  user: userReducer
})

const store = createStore(rootReducer)

// 获取数据时分层
const state = store.getState()
state.count.num
state.user.name

七、基础易错点总结

  1. reducer 绝对不能直接修改原 state,必须解构返回新对象 / 数组
  2. 只有 dispatch 能触发状态更新,直接 store.getState().count++ 无效
  3. action.type 全局唯一,多模块避免重名
  4. 异步请求(接口)原生 Redux 不支持,需要中间件 redux-thunk
  5. store 全局唯一,不能创建多个 store

八、异步基础(redux-thunk 最简)

原生 dispatch 只能传对象,thunk 支持传函数处理接口

bash

运行

复制代码
npm install redux-thunk

js

javascript 复制代码
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'

const store = createStore(reducer, applyMiddleware(thunk))

// 异步action
const fetchUser = () => {
  return async (dispatch) => {
    const res = await fetch('/api/user')
    const data = await res.json()
    dispatch({ type: 'SET_USER', payload: data.name })
  }
}

// 组件使用 dispatch(fetchUser())
相关推荐
因_崔斯汀1 小时前
Vue 模板编译:HTML 是怎么变成 JS 的?
前端·vue.js
UXbot1 小时前
帮助企业低门槛开展AI应用开发的平台推荐
前端·低代码·ui·交互·产品经理·原型模式·web app
橘子星2 小时前
基于 Vite 的多模态生图前端工程实践
前端·javascript·人工智能
想要成为糕糕手2 小时前
从零到一:CSS 3D 旋转立方体完全指南
前端·css·canvas
疯狂的魔鬼2 小时前
多角色督办任务详情页:从权限矩阵到组件拆分的完整实现
前端·vue.js·架构
恋猫de小郭2 小时前
Android 17 正式版发布,全新 AI 和各种破坏性更新
android·前端·flutter
半个落月2 小时前
从零搭建 AI 生图前端|Vite 工程化 + 通义千问 API 实战,附 API Key 安全方案
前端·人工智能
codexu_4612291872 小时前
NoteGen 里一条记录如何变成 Markdown
前端·笔记·rust·tauri
meilindehuzi_a2 小时前
从 Canvas 到 Vibe Coding:HTML5 游戏开发入门与 AI 飞机大战实战
前端·人工智能·html5