React -----Redux(状态管理工具)

本文围绕Redux和React-Redux展开,介绍了Redux作为React常用状态管理工具的优势,如集中存储管理状态、简化组件通讯等。还阐述了Redux的安装、核心概念(action、reducer、store),以及React-Redux的作用、基本使用步骤,包括获取状态和分发动作等内容。

redux中文文档

redux英文文档

npm i redux react-redux redux-thunk redux-devtools-extension axios (快捷安装) 


1.为什么用Redux

(1) Redux是React中最常用的状态管理工具(状态容器)

     React只是DOM的一个抽象层(UI库),并不是Web应用的完整解决方案。因此React在涉及到数据的处理以及组件之间的通信时比较复杂

(2) 对于大型的复杂应用来说,只用React,比较吃力

 主要的区别:组件之间的通信问题

* 不使用 Redux (图左边) :
   * 只能使用父子组件通讯、状态提升等 React 自带机制
   * 处理远房亲戚(非父子)关系的组件通讯时乏力
   * 组件之间的数据流混乱,出现 Bug 时难定位
* 使用 Redux (图右边):
   * **集中式存储和管理应用的状态**
   * 处理组件通讯问题时,**无视组件之间的层级关系**
   * 简化大型复杂应用中组件之间的通讯问题
   * 数据流清晰,易于定位 Bug

redux---------可以运行到任何与js有关的框架,vue,react等

vuex---------只能用到vue


2.redux 安装

npm i redux 


3.redux核心概念

(1)核心概念一 =========== action

        action:对象,描述要做的事情,项目中的每一个功能都是一个 action

        语法:{type:'命令', payload:'载荷'}

         特点:1、只描述做什么

                    2、JS 对象,必须带有 `type` 属性,用于区分动作的类型

                    3、根据功能的不同,可以携带额外的数据(比如,`payload` 有效载荷,也就是附带的额外的数据),配合该数据来完成相应功能

// action
// 计数器案例
{ type: 'increment' } // +1
{ type: 'decrement' } // -1

// 购物车案例
{ type: 'getGoodsList' }
{ type: 'changeGoodsState', payload: { id: 1, goodsState: true } }

(2)核心概念二 =========== reducer

         reducer:函数,用来处理 action 并更新状态,是 Redux 状态更新的地方

         语法:函数签名为:`(prevState, action) => newState`

         特点:1.注意:该函数一定要有返回值,即使状态没有改变也要返回上一次的状态

                    2.约定:reducer 是一个纯函数,并且不能包含 side effect 副作用(比如,不能修改函数参数、不能修改函数外部数据、不能进行异步操作等)

                    3.对于 reducer 来说,为了保证 reducer 是一个纯函数,不要:

                    * 不要直接修改参数 state 的值(也就是:不要直接修改当前状态,而是根据当前状态值创建新的状态值)
  
                   * 不要使用 Math.random() / new Date() / Date.now() / ajax 请求等不纯的操作
  
                   * 不要让 reducer 执行副作用(side effect)

// 干活:reducer创建store使用
// 初始值
const initialState = {
  num: 0
}
export function numReducer (state = initialState, action) {
  let newState = { ...state }
  switch (action.type) {
    case ADD:
      newState.num++
      return newState
    case SUB:
      newState.num--
      return newState
    default:
      return state
  }
}

(3)核心概念三 =========== store

        store:仓库,Redux 的核心,整合 action 和 reducer

        特点:1.一个应用只有一个store

                   2.维护应用的状态,获取状态:store.getState()

                   3.发起状态更新时:store.dispatch(action)

                   4.创建 store 时**接收 reducer 作为参数**const store = createStore(reducer)

        其他api:

                   1.订阅(监听)状态变化:const unSubscribe = store.subscribe(() => {}) 

                   2.取消订阅状态变化: unSubscribe()

// 创建 store
// 参数为:reducer 函数
const store = createStore(numReducer)

// 监听状态变化
const unSubscribe = store.subscribe(() => {
  // 状态改变时,执行相应操作
  // 比如,记录 redux 状态
  console.log(1, store.getState())
})

// 取消监听状态变化
// unSubscribe()

// 发布命令(action),执行reducer干活
store.dispatch(addAction())
store.dispatch(addAction())
store.dispatch(addAction())

  核心概念整合----小案例(index.js)

import { createStore } from "redux";

// 加/减
// 命令:动作
const ADD = "ADD",
  SUB = "SUB";

// 修改state状态会使用
export function addAction(payload) {
  return {
    type: ADD,
    payload,
  };
}

export function subAction(payload) {
  return {
    type: SUB,
    payload,
  };
}

// 干活:reducer创建store使用
// 初始值
const initialState = {
  num: 0,
};
export function numReducer(state = initialState, action) {
  let newState = { ...state };
  switch (action.type) {
    case ADD:
      newState.num+=action.payload;
      return newState;
    case SUB:
      newState.num--;
      return newState;
    default:
      return state;
  }
}

// 3. 创建 store
// 参数为:reducer 函数
const store = createStore(numReducer);

console.log("状态值为:",store, store.getState()); 

// 监控状态值的变化
const un=store.subscribe(() => {
  console.log('状态变化了',store.getState());
  
})
// 取消监控
un()


// 发起更新状态:
// 参数: action 对象
store.dispatch(addAction(10));
store.dispatch(addAction(10));
store.dispatch(subAction());
// 相当于: reducer(10, { type: 'increment' })

console.log("更新后:", store,store.getState()); 

 4.react-redux介绍

 问题:为什么要使用React-Redux绑定库?

 回答:React和Redux是两个独立的库,两者之间职责独立。因此,为了实现再React中使用Redux进行状态管理,需要一种机制,将这两个独立的库关联在一起。

 作用:为React接入Redux,实现在React中使用Redux进行状态管理

 react-redux库是Redux官方提供的React绑定库


5.react-redux 基本使用

react-redux 文档

react-redux的使用分两大步:1.全局配置(只需要配置一次,在src/index.js中) 2.组件接入(获取状态或修改状态)

步骤:1.安装 react-redux (npm install react-redux)

           2.从 react-redux 中导入 Provider 组件(全局配置中,传递数据)

           3.导入创建好的 redux 仓库 (内部包含action ,reducer, store)

           4.使用 Provider 包裹整个应用

           5.将导入的 store 设置为 Provider 的 store 属性值

核心代码:src/index.js

import ReactDOM from "react-dom";
import App from "./test";

// 导入 Provider 组件(提供store)
import { Provider } from "react-redux";
// 导入创建好的 store
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

  6. react-redux 获取状态 useSelector

   useSelector : 获取 Redux 提供的状态数据

   参数:selector 函数,用于从 Redux 状态中筛选出需要的状态数据并返回

   返回值:筛选出的状态

  import { useSelector } from 'react-redux'

// 计数器案例中,Redux 中的状态是数值,所以,可以直接返回 state 本身
const count = useSelector(state => state)

// 比如,Redux 中的状态是个对象,就可以:
const list = useSelector(state => state.list)

import { useSelector } from "react-redux"

function App(){
    // 获取 store 数据
    const count=useSelector(state=>state.num)
    console.log('获取到的store数据',count);
return(
 <div>
    <ul>
        <li>值:{count}</li>
        <li></li>
        <li></li>
    </ul>
 </div>
)
}
export default App

   7.react-redux  分发动作  useDispatch

   useDispatch: 拿到 dispatch 函数,分发action,修改redux中的状态

import { useDispatch } from 'react-redux'

// 调用 useDispatch hook,拿到 dispatch 函数
const dispatch = useDispatch()

// 调用 dispatch 传入 action,来分发动作
dispatch( action )

import { useDispatch, useSelector } from "react-redux"
function App(){
    // 获取 store 数据
    const count=useSelector(state=>state.num)
    console.log('获取到的store数据',count);

    // 修改状态
    const dispatch=useDispatch()
return(
 <div>
    <ul>
        <li>值:{count}</li>
        <li>
            <button onClick={()=>dispatch({type:'ADD',payload:5})}>+</button>
        </li>
        <li>
            <button onClick={()=>dispatch({type:'SUB'})}>-</button>
        </li>
    </ul>
 </div>
)
}
export default App

 redux 数据流


8.redux------reducer合并

 1. src/store/actions------新建count.js

// 加/减
// 命令:动作


// 修改state状态会使用
export function addAction(payload) {
  return {
    type: 'ADD',
    payload,
  };
}

export function subAction(payload) {
  return {
    type: 'SUB',
    payload,
  };
}

2. src/store/reducers---------新建count.js


// 干活:reducer创建store使用
// 初始值
const initialState = {
  num: 0,
};
export function numReducer(state = initialState, action) {
  let newState = { ...state };
  switch (action.type) {
    case 'ADD':
      newState.num += action.payload;
      return newState;
    case 'SUB':
      newState.num--;
      return newState;
    default:
      return state;
  }
}

3. src/store/reducers-------新建 list.js

// 干活:reducer创建store使用
// 初始值

export function listReducer(state = [1, 2, 3], action) {
    switch (action.type) {
        case "SUB":
            return [...state, 4];
        default:
            return state;
    }
}

4. src/store/reducers------新建 index.js(将count和list合并)

import { combineReducers } from "redux";

// 导入要合并的reducer函数
import { numReducer } from "./count";
import { listReducer } from "./list";

export const rootReducer = combineReducers({
    numReducer,
    listReducer
})

 

 5.src/store/index-----  store(抛出)

import { createStore } from "redux";
import { rootReducer } from "./reducers";

// 3. 创建 store
// 参数为:reducer 函数
const store = createStore(rootReducer);
export default store;

7.src/index----------store(全局挂载)

import ReactDOM from "react-dom";
import App from "./test";

// 导入 Provider 组件(提供store)
import { Provider } from "react-redux";
// 导入创建好的 store
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

8.页面渲染显示-------test.js

import { useDispatch, useSelector } from "react-redux"

import {addAction,subAction} from './store/actions/count'
function App(){
    // 获取 count 数据
    const count=useSelector(state=>state.numReducer.num)
    console.log('获取count数据',count);


    //  获取list数据
    const list=useSelector(state=>state.listReducer)
    console.log('获取list数据',list);

    // 修改状态
    const dispatch=useDispatch()
return(
 <div>
    <ul>
        <li>值:{count}</li>
        <li>
            <button onClick={()=>dispatch(addAction(5))}>+</button>
        </li>
        <li>
            <button onClick={()=>dispatch(subAction())}>-</button>
        </li>
        {
            list.map(item=>{
                return <li>{item}</li>
            })
        }
    </ul>
 </div>
)
}
export default App

src/store/index.js-----模板

import { createStore, applyMiddleware } from 'redux'
import rootReducer from './reducers'

import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
const middlewares = composeWithDevTools(applyMiddleware(thunk))

const store = createStore(rootReducer, middlewares)
export default store

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值