redux成员、store成员、redux的数据流转、redux如何配合react-redux使用?react-redux的常用API、react-redux、redux和vuex的区别是什么?

2023-11-06


前言

  1. Redux是为javascript应用程序提供一个可预测(根据一个固定的输入,必然会得到一个固定的结果)的状态容器。可以运行于服务端,客户端,原生应用,从Flux演变而来。简单容易上手

  2. 集中的管理react中多个组件的状态

  3. redux是专门作状态管理的js库,并不是react的插件库,也可以用在其他js框架中,例如vue,但是基本用在react中

  4. 可以同一个地方查询状态,改变状态,传播状态,用在中大项目。如下场景:组件状态需要共享,在任何地方都可以拿到,组件需要改变全局状态,一个组件需要改变另外一个组件的状态。创建store实例,其它组件导入并共享这个store实例

一、redux

1.redux三大原则

1)、单一数据源
2)、State 是只读的
3)、使用纯函数来执行修改

2.redux的安装

安装稳定版:
npm install --save redux
yarn add redux
在这里插入图片描述

附加包:多数情况下,你还需要使用 React 绑定库和开发者工具。
npm install --save react-redux
npm install --save-dev redux-devtools

3.redux成员

在这里插入图片描述

4.store成员

在这里插入图片描述

5.数据流动

在这里插入图片描述

6.redux操作流程

//安装:
yarn add redux

//一、创建reducer
// 参数:
// state:原始的state
// action:要做的事情,动作的类型
// 返回值:必须要有,是新的state(修改后的state)。getState()函数会调用reducer
// reducer要求是个纯函数(在函数内部不能修改函数的参数(输入),要有返回值)
//通过组件修改store中的state(数据)),修改store中的state(数据)后,还需要把数据响应到组件上,就需要使用 subscribe。
//它的功能是:传入旧的state,根据action对state做操作,返回新的state。
import {createStore} from 'redux'

const reducer = (state,action)=>{
  let {type,payload}=action    
  swtich (type){
  	case XXXXX :{
    	  //数据的逻辑处理
      	return {
	          ...state,
	          属性名:新的值
	      }
  	}   
  	default:
	    return state
  }
}

//二、创建state对象
// 仓库里的数据
export default {
    count:0
}

//三、创建store对象(仓库)
//使用createStore(对仓库的操作,仓库的数据)
//创建仓库时,需要说清楚仓库中存储的数据(state),以及对数据的操作(reducer)
store = createStore(reducer,state)
export default store;

//四、在组件内部使用仓库(如:获取仓库的数据,修改仓库的数据,添加,删除)
import store from '...'
store.getState() //获取状态,执行一次
store.dispatch({type:xxx,payload:ooo}) //发送action给reducer  type是必传参数
store.subscribe(回调)  //订阅 state  更新state时触发

7.action里处理异步

需要安装中间件 redux-thunk ,redux-thunk可以增强dispatch的功能,让dispatch可以接受一个函数作为参数。

./src/plugins/redux.js

//安装中间件改装 redux
import {createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'

let store = createStore(reducer,state,applyMiddleware(thunk));

./src/store/actionCreators.js

//处理异步
export let ADD =()=>((dispatch)=>{
    axios({
        url:"http://localhost:3000/inc",
    })
    .then(res=>{
        dispatch({
            type:"INCREMENT",
            payload:res.data.num
        })
    })
})


App组件
./src/App.js

import { increment,decrement,ADD } from "./store/actionCreators";

store.dispatch(ADD());

8.combineReducers提取reducer

当应用逻辑逐渐复杂的时候,我们就要考虑将巨大的 Reducer 函数拆分成一个个独立的单元,这在算法中被称为 ”分而治之“,拆分后的reducer 在 Redux 中实际上是用来处理 Store 中存储的 State 中的某一个数据,一个 Reducer 和 State 对象树中的某个属性对应。
把一个大的reducer拆成若干个小的。注意:把大的state也分开,并且放在每个reducer。也就是说,每个reducer里面写上它要操作的数据,这样的话,在一个reducer里包含了,数据(state)和数据的操作(reducer)。

// ./src/plugins/myRedux.js

import {createStore,applyMiddleware,combineReducers} from 'redux'
import thunk from 'redux-thunk'
import count from "../store/reducers/count";
import todos from "../store/reducers/todos";

let rootReducer = combineReducers({
    todos:todos,
    count:count
});
//去掉了第二个参数state(因为state拆分到了每个reducer里了)
export default createStore(rootReducer,applyMiddleware(thunk));


// ./src/store/reducers/count.js

// 是当前reducer要操作的数据
let initCount = 8;

const count = (count=initCount,action)=>{    
    switch(action.type){
        case "INCREMENT":{
            return count+action.payload;
        }
        case "DECREMENT":{
            return count-action.payload;
        }
        default: return count;
    }
}

export default count;


// ./src/store/reducers/todos
let initState=[] //当前reducer所操作的数据,放在里自己的模块里。

const todos = (todos, action) => {
  switch (action.type) {
    case "ADD_TODO": {
      return [
        ...todos,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ]
    }

    case "REMOVE_TODO": {
      const { id } = action;
      todos.map((item,index) => item.id ===id && todos.splice(index, 1));
      return [...todos]
    }

    case "CHECK_TODO": {
      const { id } = action;
      todos.map((item,index) => item.id ===id && (todos[index].completed=!todos[index].completed));
      return [...todos]
    }

    default:
      return todos;
  }
};

export default todos;

//删除掉state文件。

//组件里:
写法基本上不变
store.getState().todos

state数据不写在类内部订阅,可以写在主入口文件 订阅store数据的更新

二、react-redux

1.redux里出现的问题:

1)、组件中出现了大量的store对象

2)、在redux里,凡是使用state里数据的组件,必须加上 store.subscribe() 函数,否则,数据不是响应式的

2. react-redux做了哪些事情?

基于redux思想,专门为react使用redux而生,react-redux是连接redux和react组件的桥梁

3. 安装

npm install --save react-redux

4. react-redux的API

1)、组件:可以让组件拿到state
即不需要使用传统的subscribe()来监听state重绘组件

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

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

2)、connect(): 链接 ,(返回值)是个高阶组件,用来链接react组件和redux
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
功能:把store和react组件联系在一起。只要store发生了变化就会调用mapStateToProps方法。Connect方法就是个高阶组件。

参数1:mapStateToProps函数
功能: 把仓库里的state合并到props里。给mapStateToProps函数传入所有state,它返回指定的state数据(需要合并到组件props中的state)。返回的state与组件的 props 合并。
所以,当store发生变化时,mapStateToProps方法就会更新组件里的props,那么组件就更新了(因为props变了)。

参数:state:所有的state
返回值:指定的state(组件里需要的state)。

实例代码:
const mapStateToProps = (state)=>{
      return {
           count:state.count
      }
}

参数2:mapDispatchToProps函数

功能:

​ 把dispatch和props联系起来。传入dispatch,返回绑定好的action方法。
​ 更改数据必须要触发action,所以,mapDispatchToProps把 action 作为组件的props 进行绑定(联系的体现),要派发的函数名,可以是多个函数。mapDispatchToProps 就是用于建立组件跟store.dispatch(是action)的映射关系。

参数:

dispatch: 派发
​ **ownProps:**当前组件的props,即使用标签时,传入的props

返回值:
对象:表示所有dispatch的对象

 **示例代码:**

import React from "react";
import './App.css';
import {ADD,REDUCE} from "./store/action";
import {connect} from "react-redux";

class App extends React.Component {

  add(){
    this.props.add();
  }

  reduce(){
    this.props.reduce();
  }

  render = () => {
      return (
          <div className="App">
            <p>{this.props.count}</p>
            <input type="button" value=" 加 " onClick={()=>this.add()} />
            <input type="button" value=" 减 " onClick={()=>this.reduce()} />            
          </div>
        )
    }
}

export default connect((state)=>{
  return {
    count:state.count
  }
},dispatch=> ({
  add: () => dispatch(ADD()),
  reduce: () => dispatch(REDUCE())  
}))(App);

5. react-redux的实现

安装:npm install --save react-redux

//1、主入口文件 index.js
import {Provider} from 'react-redux'
import store from './plugins/redux'

<Provider store={store}>
  <App/>
</Provider>
  
 //2、容器组件里:App组件
 
import {connect} from "react-redux";
 
class App extends React.Component {
  add(){
    //直接用props来调用dispatch,而不需要store
    this.props.dispatch({
      type:"INCREMENT",
      payload:2
    });
  }
    
  render = () => (
   	 <div className="App">
        <p>{this.props.count}</p>  //  使用props可以直接拿到state里的数据,而不需要store
        <input type="button" value=" 加 " onClick={()=>this.add()} />
     </div>
   )    
}

 //容器组件对外开放时,(把redux里的state转到props) 
export default connect((state)=>{
  return {
    count :state.count    
  }
})(App);

三、react-redux、redux和vuex的区别

在这里插入图片描述

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redux成员、store成员、redux的数据流转、redux如何配合react-redux使用?react-redux的常用API、react-redux、redux和vuex的区别是什么? 的相关文章