【Redux】Redux 基本使用

1. Redux 快速上手

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

<button id="decrement">-button>
<span id="count">0span>
<button id="increment">+button>

<script src="https://unpkg.com/redux@latest/dist/redux.min.js">script>

<script>
  // 1. 定义 reducer 函数 
  // 根据不同的 action 对象,返回不同的 state
  // state 管理数据的初始状态
  // action 对象的 type 属性标记需要做的修改操作
  function reducer (state = { count: 0 }, action) {
    switch (action.type) {
      case 'INCREMENT':
        // state 是对象,所以返回的数据也是对象
        return { count: state.count + 1 }
      case 'DECREMENT':
        return { count: state.count - 1 }
      default:
        return state
    }
  }
  // 2. 使用reducer函数生成store实例
  const store = Redux.createStore(reducer)

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

  })
  // 4. 通过 store 的 dispatch 函数提交 action 的更改状态
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click', () => {
    // 匹配的是 action 对象,所以传入 action 对象
    store.dispatch({
      type: 'INCREMENT'
    })
  })
  // 减
  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click', () => {
    store.dispatch({
      type: 'DECREMENT'
    })
  })
script>

【Redux】Redux 基本使用_第1张图片

2. React 中使用 Redux

2.1 配制环境

  1. Redux Toolkit(RTK)- 官方推荐编写Redux逻辑的方式,简化书写方式
  2. react-redux - 用来链接 Redux 和 React组件的中间件
npx create-react-app react-redux-demo
npm i @reduxjs/toolkit  react-redux 

2.2 使用 RTK

创建 counterStore

// @/store/modules/counterStore.js
import { createSlice } from '@reduxjs/toolkit'

const counterStore = createSlice({
  // 模块名称唯一
  name: 'counter',
  // 初始 state
  initialState: {
    count: 1
  },
  // 修改数据的同步方法 支持直接修改
  reducers: {
    increment (state) {
      state.count++
    },
    decrement(state){
      state.count--
    },
    addToNum(state, action) {
      state.count = action.payload
    }
  }
})
// 解构出 actionCreater 函数
const { increment,decrement, addToNum } = counterStore.actions

// 获取 reducer 函数
const counterReducer = counterStore.reducer

// 导出
export { increment, decrement, addToNum }
export default counterReducer
// @/store/modules/channelStore.js
import { createSlice } from "@reduxjs/toolkit"
import axios from "axios"

const channelStore = createSlice({
  name: 'channel',
  initialState: {
    channelList: []
  },
  reducers: {
    setChannels (state, action) {
      state.channelList = action.payload
    }
  }
})


// 异步请求部分
const { setChannels } = channelStore.actions

const fetchChannlList = () => {
  return async (dispatch) => {
    const res = await axios.get('http://geek.itheima.net/v1_0/channels')
    dispatch(setChannels(res.data.data.channels))
  }
}

export { fetchChannlList }

const reducer = channelStore.reducer

export default reducer

// @/store/index.js
import { configureStore } from '@reduxjs/toolkit'

import counterReducer from './modules/counterStore'

export default configureStore({
  reducer: {
    // 注册子模块
    counter: counterReducer
  }
})

为 React 注入 store

// @/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
// 导入store
import store from './store'
// 导入store提供组件Provider
import { Provider } from 'react-redux'

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

在 React 组件中使用修改 store 中的数据

// App.js
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
// 导入actionCreater
import { inscrement, decrement, addToNum } from './store/modules/counterStore'
import { fetchChannlList } from './store/modules/channelStore'

function App () {
  // useSelector 函数将 store 中的数据映射到组件中 counter 是 store 名字
  const { count } = useSelector(state => state.counter)
  const { channelList } = useSelector(state => state.channel)
  const dispatch = useDispatch()
  // 使用useEffect触发异步请求执行
  useEffect(() => {
    dispatch(fetchChannlList())
  }, [dispatch])
  return (
    <div className="App">
      <button onClick={() => dispatch(decrement())}>-</button>
      {count}
      <button onClick={() => dispatch(inscrement())}>+</button>
      {/* 变为10 和 变为20 */}
      <button onClick={() => dispatch(addToNum(10))}>add To 10</button>
      <button onClick={() => dispatch(addToNum(20))}>add To 20</button>
      <ul>
        {channelList.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
  )
}

export default App

你可能感兴趣的:(Redux,javascript,前端,react.js)