Skip to content

redux ​

Redux 是 React 最常用的集中状态管理工具,类似于 Vue 中的 Pina/Vuex, 可以独立于框架运行。

作用:通过集中管理的方式管理应用的状态。

Redux数据流

使用步骤: ​

  1. 定义一个 reducer函数(根据当前想要做的修改返回一个新的状态)
  2. 使用 createStore方法 传入 reducer 函数, 生成一个 store 实例对象
  3. 使用 store 实例 的 subscribe 方法 订阅数据的变化(数据一旦变化,可以得到通知)
  4. 使用 store 实例的 dispatch 方法提交 action 对象 触发数据变化(告诉 reducer 怎么改数据)
  5. 使用 store 实例的 getState 方法 获取最新的状态数据更新到视图中
HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/redux/4.0.0/redux.js"></script>
  </head>
  <body>
    <button id="decrement">-</button>
    <span id="count">0</span>
    <button id="increment">+</button>
    <script>
      // 1. 定义reducer函数
      // 作用:根据不同的action对象,返回不同的新的state
      // state: 管理的数据初始状态
      // action: 对象type标记当前想要做什么样的修改
      function reducer(state = { count: 0 }, action) {
        // 数据不可变:基于原生状态生成一个新的状态
        if (action.type === 'INCREMENT') {
          return { count: state.count + 1 }
        }
        if (action.type === 'DECREMENT') {
          return { count: state.count - 1 }
        }
        return state
      }

      // 2. 使用reducer函数生成store实例
      const store = Redux.createStore(reducer)

      // 3. 通过store实例的subscribe订阅数据变化
      // 回调函数可以在每次state发生变化的时候自动执行
      store.subscribe(() => {
        console.log('state变化了...', store.getState())
        document.getElementById('count').innerHTML = store.getState().count
      })

      // 4. 通过store实例的dispatch函数提交action更改状态
      const inBtn = document.getElementById('increment')
      inBtn.addEventListener('click', () => {
        store.dispatch({ type: 'INCREMENT' })
      })

      const dBtn = document.getElementById('decrement')
      dBtn.addEventListener('click', () => {
        store.dispatch({ type: 'DECREMENT' })
      })
    </script>
  </body>
</html>

Redux 在 react 项目中的环境准备 ​

在 React 中使用 redux,官方要求安装两个其他的插件 Redux Toolkit 、 react-redux

bash
npm i @reduxjs/toolkit react-redux
  • Redux Toolkit: 是官方推荐编写 Redux 逻辑的方式,是一套工具的集合,简化书写方法

    1. 简化 Store 的配置方式
    2. 内置 immer 支持可变式状态修改
    3. 内置 thunk 更好的异步创建
  • react-redux:用来 链接 Redux 和 React 组件的中间件

Redux和React的关系

在 React 中使用 redux ​

Redux和React的关系

1.使用 React Toolkit 创建 counterStore ​

jsx
import { createSlice } from '@reduxjs/toolkit'

const counterStore = createSlice({
  name: 'counterStore'
  initialState: {
    count: 0
  },
  reducers: {
    increment: state => {
      state.count++
    },
    decrement: state => {
      state.count--
    }
  }
})

const { increment, decrement } = counterStore.actions;

const counterReducer = counterStore.reducer;

export { increment, decrement };
export default counterReducer;
jsx
import { configureStore } from '@reduxjs/toolkit'

import counterStore from './modules/counterStore'

const store = configureStore({
  reducer: {
    counterStore: counterStore.reducer
  }
})

export default store

2. 为 react 注入 store ​

react-redux 负责把 Redux 和 React 链接起来,内置 Provider 组件,通过 store 参数把创建好的 store 实例注入到应用中,链接正式建立

jsx
import store from './store'
import { Provider } from 'react-redux'

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

3.React 组件中使用 store 中的数据 ​

在 React 组件中使用 store 中的数据,需要用到一个钩子函数 useSelector, 它的作用是把 store 中的数据映射到组件中

jsx
import { useSelector } from 'react-redux'

function ReduxExample() {
  const { count } = useSelector((state) => state.counter)
  return <div>{count}</div>
}

4.修改 store 中的数据 ​

在 React 组件中修改 store 中的数据,需要用到一个 useDispatch 钩子函数,它的作用是返回一个函数,可以用来触发 store 中的 reducer 函数,修改数据

jsx
import { useSelector, useDispatch } from 'react-redux'

import { increment, decrement } from './store/modules/counterStore'

function ReduxExample() {
  const { count } = useSelector((state) => state.counter)
  const dispatch = useDispatch()
  return (
    <div>
      <button onClick={() => dispatch(increment())}>-</button>
      <span>{count}</span>
      <button onClick={() => dispatch(decrement())}>+</button>
    </div>
  )
}