React-redux

redux是专门为react设计的状态管理工具。虽然专门为react设计,但是也可以脱离react独自使用。

redux的状态管理思想是:将整个应用的所有状态都集中在一个唯一的store中进行管理,store中的状态只能通过设定的方法进行修改。

这样做的好处是可以保证store中的状态都是以可预测的形式进行变化,易维护,易监听。

在react项目中使用redux要下载redux和react-redux两个依赖项。

npm i redux --save
npm i react-redux --save 
npm i redux-thunk -save:需要异步操作的话

 

代码展示:

./src/store/reducer.js

import {combineReducers} from "redux"
// 创建redux的store,需要先指定store中的状态有哪些

// 使用函数定义一个store中的状态。函数名就是状态名。
// 次函数有两个参数:1.state表示这个状态的初始值 2.action表示对这个状态的修改行为
function num(state=100,action){
    console.log("num状态");
    switch (action.type) {
        case "NUM_DECREASE":
            return state - 1;
        case "NUM_INCREASE":
            return state + 1;
        case "SET_NUM":
            return action.content;
        default:
            return state;
    }
}

function txt(state="helloworld",action){
    switch (action.type) {
        case "SET_TXT":
            return action.content;
        case "CLEAR_TXT":
            return "";
        default:
            return state;
    }
}

function obj(state={name:"张",age:18},action){
    switch (action.type) {
        case "SET_OBJ_NAME":
            // 对于非基本数据类型的改变,例如修改对象的属性或者修改数组中的元素,react的推荐做法是对
            // 源数据直接进行拷贝然后赋值修改,这样可以保证历史状态不被修改。
            // return Object.assign({},state,{name:action.content});
            return {...state,...{name:action.content}}
        default:
            return state;
    }
}

function list(state=[],action){
    switch (action.type) {
        case "SET_LIST":
            return action.content;
        default:
            return state;
    }
}


// 所有的状态都准备完毕之后,需要使用 combineReducers 函数将所有的状态合并为一个 reducer 对象(本质是一个action处理函数)
// combineReducers 函数参数是一个对象,对象中要包含所有的状态数据。
export default combineReducers({num,txt,obj,list})

./src/store/actions.js

// 修改store中的状态,必须使用提交action的形式修改数据。

// 在actions.js中需要为每一个action都创建一个函数,函数中必须返回action对象。
// action本质是一个对象,其中必须包含type属性,用于表示本次修改数据的操作类型。
// 除了type之外,还可以添加任意其他属性作为本次修改操作的参数。
function numDecrease() {
    return {
        type: "NUM_DECREASE"
    }
}

function numIncrease() {
    return {
        type: "NUM_INCREASE"
    }
}

function setNum(content) {
    return {
        type: "SET_NUM",
        content
    }
}

function setTxt(content) {
    return {
        type: "SET_TXT",
        content
    }
}

function clearTxt() {
    return {
        type: "CLEAR_TXT",
    }
}

function setObjName(content) {
    return {
        type: "SET_OBJ_NAME",
        content
    }
}

function setList(content) {
    return {
        type: "SET_LIST",
        content
    }
}

// 异步修改reducer中的状态
function requestList() {
    // 异步修改的action是一个函数,函数总需要返回异步任务的promise(要做的操作)
    return dispatch => {
        let p = new Promise(function (resove, reject) {
            // 利用延时器模拟一个网络请求
            setTimeout(() => {
                let data = [1, 2, 3, 4, 5];
                resove(data);
            }, 3000);
        });
        // 异步任务完成之后,还是需要通过提交同步的action行为修改数据(提交setList方法,修改reducer中的list)
        p.then(data => {
            dispatch(setList(data));
        });
        return p;
    }
}


export {
    numDecrease,
    numIncrease,
    setNum,
    setTxt,
    clearTxt,
    setObjName,
    requestList
}

./src/store/store.js

// 创建仓库对象
import {createStore,applyMiddleware} from "redux"
// 导入所有的状态
import reducer from "./reducer"
// 如果要使用异步数据修改action,则需要引入异步操作的中间件 thunk
import thunk from "redux-thunk"

// 使用 createStore 函数创建 store 对象,参数:1.是状态reducer 2.导入的各种中间件
export default createStore(reducer,applyMiddleware(thunk));

./src/views/MyCom.js

import React from "react"
import "./MyCom.css"
import {connect} from "react-redux"

import {setTxt,clearTxt,setObjName,requestList} from "../store/actions"

class MyCom extends React.Component{
    constructor(props){
        super(props);
        this.state = {};
    }
    render(){
        return (
            <div>
                <hr/>
                <p>{this.props.num}</p>

                <p>{this.props.txt}</p>
                <input type="text" value={this.props.txt} onChange={this.props.setTxt} />
                <button onClick={this.props.clearTxt}>清除</button>

                <p>{this.props.obj.name},{this.props.obj.age}</p>
                <button onClick={()=>{this.props.setObjName(this.props.txt)}}>修改姓名</button>

                <p>{this.props.list.toString()}</p>
                <button onClick={this.props.requestList}>发起网络请求</button>
            </div>
        )
    }
}

export default connect(state=>{
    return {
        num: state.num,
        txt: state.txt,
        obj: state.obj,
        list: state.list
    }
},dispatch=>{
    return {
        setTxt:(e)=>{
            // console.log("我要修改txt的值:" + e.target.value);
            dispatch(setTxt(e.target.value));
        },
        clearTxt:()=>{
            dispatch(clearTxt());
        },
        setObjName: (name)=>{
            dispatch(setObjName(name));
        },
        requestList:()=>{
            dispatch(requestList()).then(function(){
                console.log("数据请求完成");
            });
        }
    }
})(MyCom);

./src/App.js

import React, { Component } from 'react';
import './App.css';

// 在组件中使用 store 中的状态,需要使用一个高阶组件 connect 函数
import {connect} from "react-redux"

// 在组件中导入要使用的action
import {numDecrease,numIncrease,setNum} from "./store/actions"

import MyCom from "./views/MyCom"

class App extends Component {
  constructor(props){
    super(props);
    this.state = {}
  }
  render() {
    return (
      <div className="App">
      <button onClick={this.props.numInc}>+</button>
        {/* 从store中map到组件中的数据会存在组件的props属性中 */}
        <span>{this.props.num}</span>
        <button onClick={this.props.numDec}>-</button>
        <br/> 
        <input type="number" onChange={(e)=>{this.props.setNum(e.target.value)}}/>
        <MyCom></MyCom>
      </div>
    );
  }
}

// connect有两个参数,
// 1.映射仓库中的状态,类型是一个回调函数,在回调函数中返回对应的状态
// 2.映射action中的函数,类型是一个回调函数,在回调函数中返回对应的action方法
// 返回值又是一个函数(高阶组件),功能是把组件改造为映射之后的新组件
/*let func = connect(state=>{
  return {
    num: state.num
  }
},dispatch=>{
  // dispath提交action中的方法
  return{
    numDec:()=>{
      dispatch(numDecrease());
    },
    numInc:()=>{
      dispatch(numIncrease());
    }
  }
});
export default func(App);*/

export default connect(state=>{
  return {
    num: state.num
  }
},dispatch=>{
  // dispath提交action中的方法
  return{
    numDec:()=>{
      dispatch(numDecrease());
    },
    numInc:()=>{
      dispatch(numIncrease());
    },
    setNum:(n)=>{
      dispatch(setNum(n));
    }
  }
})(App);


// 流程:状态的声明->仓库的创建->仓库注入到项目中->组件使用仓具的数据->修改仓库的数据

// 异步操作状态数据,高级用法明天讲
// 作业:
// 1.通过看回放,练习redux基础使用
// 2.在reducer.js 文件中,除了num,之外再定义其他一些类型,然后在actions定义修改方法
//   比如:定义string,定义object(对象),定义列表(数组),添加修改方法(直接附上对应的值就行)



./src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

// 在react项目中使用redux,要在项目程序的入口文件中导入 Provider 组件
import {Provider} from "react-redux"
// 导入仓库对象
import store from "./store/store"

ReactDOM.render(
  // 使用Provider组件将store注入到整个react项目中,注入之后在项目的所有组件都可以访问store
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值