1. 安装依赖 两个包
npm i redux react-redux --dev //或者(yarn add)
2. 在 src/store/reducers/index.js 管理员 负责数据操作记录
3. 在 src/store/index.js 仓库
4. 在入口的js文件 index.js 来引入 store 入口文件引入后组件就可以使用
1. 需要将 store和 App.js 产生一些联系 (使用redux的连接器,入口文件和仓库管理员产生链接)组件
5. 在App.js中 使用store中的数据
管理员文件(包含派发流程)
//在管理员的index内定义默认的数据
const defaultState = {
num: 1000
}
//暴露数据出去,
// state的数据,就可以在外面使用了
// 通过action方法处理改变state内的数据
export default (state = defaultState, action) => {
//对所有派发数据修改修改事件,都进行判断
if (action.type === 'change') {
//说明是数字修改的派发事件
let newState = JSON.parse(JSON.stringify(state)) //必须要深克隆,否则无法触发视图更新
newState.num += action.value //改变管理员的值
return newState //需要返回值
}
return state
}
在仓库内链接管理员,并且暴露出去
//引入管理员暴露的数据模块
import reducers from "./reducers/index"
//引入redux内的仓库生成器方法
import { createStore } from 'redux'
//将管理员和仓库一起导出去(生成仓库)
export default createStore(reducers)
入口文件挂载仓库
// 引入仓库文件
import store from './store/index'
// 引入redux和react的连接器的方法
import { Provider } from 'react-redux'
//将Provider包裹住App ,并且在标签上传入store数据
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
使用方式(组件)
//引入连接器(将仓库和当前组件链接起来,
import { connect } from 'react-redux'
//state就是在管理员那里声明过的state了,而state= defaultState 所以,拿到数据后,直接给了num
const mapStateToProps = state => {
return {
num: state.num
}
}
在组件内触发该事件<button onClick={this.props.changeNum}>+</button>
//派发修改仓库数据的方法
//数据修改时,进行派发的方法
const mapDispatch = dispatch => {
return {
changeNum: () => {//组件需要触发的事件,一旦触发就立即派发了change
// 创建action,该名称并不是写死的,只是派发了一个修改的独享过去
const action = {
type: 'change', //派发修改操作的名称,在仓库那边可以通过此名称进行验证的
value: 1 //需要更改的值每次点击的时候,更改多少数据
}
dispatch(action) //开始派发这一事件
}
}
}
//将当前组件和仓库链接起来,store的数据就可以在组件内使用
export default connect(mapStateToProps, mapDispatch)(CarouselImg)
//第一个放数据,第二个放方法的
connect(mapStateToProps, null)(CarouselImg)
使用方式
{this.props.num} //即可得到当前仓库内的数据
Store仓库负责连接管理和组件,所有的数据,都在管理员文件内
在组件内派发事件this.props.事件名(changeNum)
获取仓库数据this.props.num
注意
如果当前组件内,还有其他的组件,要用{...this.props}传给子组件,否则,其他的子组件是没有仓库内的数据的,
如果按钮组件被封装了,但是连接器只连接到了当前组件,还要给按钮组件传入props
class AddButton extends Component {
render() {
console.log(this.props)//空
return <button onClick={this.props.changeNum}>+</button>
}
}
父组件
<button onClick={this.props.jian}>-</button>
{this.props.num}
<AddButton {...this.props}></AddButton> //rudex的数据,在当前注册时,就只给了父组件,子组件没有。如果需要用props内的
方法和数据,需要手动的添加到子组件上
常量优化
避免因为字符写错出问题,如果用常量,则写错后提示报错
1 在reducers同层级新建actionType文件夹新建index.js
2 导入常量
export const CHANGE_NUM = 'CHANGE_NUM'
管理员文件redux内判断也要更改
import { CHANGE_NUM } from '../actionsType/index' //引入定义的常量
if (action.type === CHANGE_NUM) {
//说明是数字修改的派发事件
let newState = JSON.parse(JSON.stringify(state)) //必须要深克隆,否则无法触发视图更新
newState.num += action.value //改变管理员的值
return newState //需要返回值
}
4派发方法的组件内引入常量
import { CHANGE_NUM } from '../store/actionsType/index'
changeNum: () => {
//组件需要触发的事件,一旦触发就立即派发了change
// 创建action
const action2 = {
type: CHANGE_NUM, //派发修改操作的名称,在仓库那边可以通过此名称进行验证的
value: 1 //需要更改的值每次点击的时候,更改多少数据
}
dispatch(action2)
},
派发事件的单独封装
reducers文件夹同层级新建文件夹actionCreator 下index
保存所有的派发事件
import { JIAN_NUM } from '../actionsType/index' //引入外部命名的常量
//暴露出派发的事件 可通过调用numJian 传入num 动态修改减少的数量
export const numJian = (num) => {
return {
type: JIAN_NUM,
value: num
}
}
在组件内导入actionCreator内的index
import { numJian } from '../store/actionCreator/index' //派发的方法
//数据修改时,进行派发的方法
const mapDispatch = dispatch => {
return {
jian: () => {
//实际上抽离代码,放在另外一个地方了
dispatch(numJian(1))
}
}
}
拆分合并多个reduers
store/reducers/1.js
store/reducers/2.js
两个代码一样
引入要合并的管理员文件
import data1 from "./1";
import data2 from "./2";
// 2 引入 合并工具
import { combineReducers } from "redux";
// 3 合并并导出
export default combineReducers({data1,data2});
//取数据的时候,会有影响
const mapStateToProps = (state) => {
console.log(state);
return {
// 修改成 1 多加了一层
num: state.data1.num
}
}
异步修改action
store/actionTypes/index.js 新增异步常量名
export const START_NUM = 'START_NUM'
下包
npm i redux-thunk axios --dev
在仓库内,重新载入下好的异步模块(修改)
//引入redux内的连接器 在加入另外一个连接器
import { createStore,applyMiddleware } from 'redux'
//引入异步工具
import reduxThunk from 'redux-thunk'
//将管理员和仓库一起导出去(修改)
export default createStore(reducers, applyMiddleware(reduxThunk))
store/actionCreator/index内新增异步请求
import { START_NUM } from '../actionsType/index.js' //引入定义好的常量名
//初始化异步请求
export const startNum = () => {
return dispatch => {
setTimeout(() => {
const action = {
type: START_NUM,
value: 999999
}
dispatch(action)
}, 2000)
}
}
在组件内引入并且调用
import {startNum } from '../store/actionCreator/index' //派发的方法
componentDidMount() {
生命周期,在页面初始化的时候调用
this.props.startcNum() //触发redux内异步方法
}
const mapDispatch = dispatch => {
//异步数据请求
startcNum:()=>{
dispatch(startNum()) //异步方法的定义
}
}
export default connect(mapStateToProps, mapDispatch)(CarouselImg)
redux管理员处理异步回来的数据
import {START_NUM } from '../actionsType/index'
//在管理员的index内定义默认的数据
const defaultState = {
num: 1000
}
//暴露数据出去,
// state的数据,就可以在外面使用了
// 通过action方法处理改变state内的数据
export default (state = defaultState, action) => {
//对所有派发数据修改修改事件,都进行判断
let newState = JSON.parse(JSON.stringify(state)) //必须要深克隆,否则无法触发视图更新
//异步更新
console.log(action)
if (action.type === START_NUM) {
newState.num = action.value
return newState //需要返回值
}
return state
}