赞
踩
1. redux是一个专门用于做状态管理
的JS库;
2. 它可以用在react, angular, vue等项目中, 但基本与react配合使用;
3. 作用: 集中式管理react应用中多个组件共享的状态。
纯函数
。作用:创建包含指定reducer的store对象
作用:应用上基于redux的中间件(插件库)
作用:合并多个reducer函数
运行结果
文件目录结构
1、创建store,store.js
/*该文件专门用于暴露一个store对象,整个应用只有一个store对象*/
//1、引入createStore,专门用于创建redux中最为核心的store对象,applyMiddleware:执行中间件
import {createStore, applyMiddleware} from "redux";
//2、引入为count组件服务的reducer
import countReducer from "./count_reducer";
//3、引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";
//4、暴露store
export default createStore(countReducer, applyMiddleware(thunk));
2、count_reducer
/* * 1、初始化状态 * 2、加工状态 * 该文件用于创建一个为count组件服务的reducer,reducer的本质就是一个函数; * reducer会接收到两个参数,分别为:之前的状态(preState),行为(action) * */ import {INCREMENT,DECREMENT} from "./constant"; const initState = 7; function countReducer(preState = initState, action) { console.log(preState, action); const {type, data} = action; switch (type) { case INCREMENT://加 return preState + data; case DECREMENT://减 return preState - data; default: return preState } } export default countReducer
3、count_action.js
/*该文件专门为count组件生成action对象*/ import {INCREMENT, DECREMENT} from "./constant"; import store from "./store"; //同步action,就是指action的值为object类型的一般对象 export const createIncrementAction = data => ({type: INCREMENT, data}) export const createDecrementAction = data => ({type: DECREMENT, data}) //所谓的异步action,就是指action的值为函数,需要使用一个中间插件, // 异步action中一般都会调用同步action,异步action不是必须要用的 export const createIncrementAsyncAction = (data, time) => { //返回的是一个函数 return () => { setTimeout(() => { store.dispatch(createIncrementAction(data)) }, time) } }
4、constant.js
/*
* 该模块是用于定义action对象中type类型的常量值,
* 便于管理的同时,当值程序员单词写错,降低单词拼写出错率*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
5、count/index.js
import React, {Component} from 'react'; //1、引入store,用于获取redux中保存的状态 import store from "../../redux/store"; //2、引入actionCreator,专门用于创建对象 import {createDecrementAction, createIncrementAction, createIncrementAsyncAction} from "../../redux/count_action"; export default class Count extends Component { /* componentDidMount() { //5、组件挂载完成后监测redux中的状态变化,只要变化就调用render渲染页面 store.subscribe(() => { this.setState({}) }) }*/ increment = () => { const {value} = this.selectNumber; // 4、通知redux加value(store.dispatch进行行为派发) store.dispatch(createIncrementAction(value * 1)) } decrement = () => { const {value} = this.selectNumber; store.dispatch(createDecrementAction(value * 1)) } //奇数再加 incrementIfOdd = () => { const {value} = this.selectNumber; const count = store.getState() if (count % 2 !== 0) { store.dispatch(createIncrementAction(value * 1)) } } //异步加 incrementAsync = () => { const {value} = this.selectNumber; store.dispatch(createIncrementAsyncAction(value * 1, 500)) } render() { return ( <div> {/*3、store.getState()获取状态*/} <h1>当前求和为:{store.getState()}</h1> <select ref={c => this.selectNumber = c}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select><br/><br/> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button> </div> ) } }
监测redux的状态变化也可以在index.js入口文件中完成
import App from './App'; import store from "./redux/store"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App/> </React.StrictMode> ); //监测redux状态变化的api写在这里,就不用每个组件都需要调用store.subscribe // 检测redux 状态 发生变化 整个app 都调用 render() 作用是不用重复写 componentDidMount store.subscribe(() => { root.render( <React.StrictMode> <App/> </React.StrictMode> ); })
6、App.js
在App.js文件中引入组件count/index.js
让所有组件都可以得到state数据
root.render(
/*Provider让所有组件都可以得到state数据*/
<Provider store={store}>
<App/>
</Provider>
);
用于包装 UI 组件生成容器组件
export const CountContainer = connect(
mapStateToProps,
mapDispatchToProps)(CountUI)
将外部的数据(即state对象)转换为UI组件的标签属性
const mapStateToProps = (state) => {
//返回值是一个对象
return {count: state}
}
将分发action的函数转换为UI组件的标签属性
运行效果
文件目录结构
3.components/count/index.js
import React, {Component} from 'react'; export default class Count extends Component { increment = () => { const {value} = this.selectNumber; this.props.jia(value * 1) } decrement = () => { const {value} = this.selectNumber; this.props.jian(value * 1) } //奇数再加 incrementIfOdd = () => { const {value} = this.selectNumber; if (this.props.count % 2 !== 0) { this.props.jia(value * 1) } } //异步加 incrementAsync = () => { const {value} = this.selectNumber; this.props.jiaAsync(value * 1,500) } render() { console.log('UI组件', this.props); return ( <div> <h1>当前求和为:{this.props.count}</h1> <select ref={c => this.selectNumber = c}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select><br/><br/> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button> </div> ) } }
//这是一个容器组件 //1、引入connect用于连接UI组件与redux import {connect} from "react-redux"; //2、引入Count的UI组件 import CountUI from "../../components/count"; //3、引入action import {createIncrementAction, createDecrementAction, createIncrementAsyncAction} from "../../redux/count_action"; /* * 1、mapStateToProps函数的返回是一个对象 * 2、返回的对象中key就作为状态传递给UI组件props的key,value就作为传递给UI组件props的值value * 3、mapStateToProps用于传递状态*/ const mapStateToProps = (state) => { //返回值是一个对象 return {count: state} } /* * 1、mapDispatchToProps函数的返回是一个对象 * 2、返回的对象中key就作为状态传递给UI组件props的key,value就作为传递给UI组件props的值value * 3、mapStateToProps用于传递操作状态的方法*/ const mapDispatchToProps = (dispatch) => { return { jia: (data) => { dispatch(createIncrementAction(data)) }, jian: (data) => { dispatch(createDecrementAction(data)) }, jiaAsync: (data, time) => { dispatch(createIncrementAsyncAction(data, time)) } } } //4、connect()()创建并暴露Count的容器组件 //connect()第一次调用的时候必须传入两个参数,两个参数必须是函数 export const CountContainer = connect( mapStateToProps, mapDispatchToProps)(CountUI) /*简写 1. */ /*export const CountContainer = connect( state => ({count: state}), /!* //mapDispatchToProps的一般写法 dispatch => ({ jia: data => dispatch(createIncrementAction(data)), jian: data => dispatch(createDecrementAction(data)), jiaAsync: (data, time) => dispatch(createIncrementAsyncAction(data, time)) })*!/ //mapDispatchToProps的简写 { //reaact-redux会自动进行派发 jia:createIncrementAction, jian:createDecrementAction, jiaAsync:createIncrementAsyncAction } )(CountUI)*/
/*该文件专门用于暴露一个store对象,整个应用只有一个store对象*/
//1、引入createStore,专门用于创建redux中最为核心的store对象,applyMiddleware:执行中间件
import {createStore, applyMiddleware} from "redux";
//2、引入为count组件服务的reducer
import countReducer from "./count_reducer";
//3、引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";
//4、暴露store
export default createStore(countReducer, applyMiddleware(thunk));
/* * 1、初始化状态 * 2、加工状态 * 该文件用于创建一个为count组件服务的reducer,reducer的本质就是一个函数; * reducer会接收到两个参数,分别为:之前的状态(preState),行为(action) * */ import {INCREMENT,DECREMENT} from "./constant"; const initState = 7; function countReducer(preState = initState, action) { console.log(preState, action); const {type, data} = action; switch (type) { case INCREMENT://加 return preState + data; case DECREMENT://减 return preState - data; default: return preState } } export default countReducer
/*该文件专门为count组件生成action对象*/ import {INCREMENT, DECREMENT} from "./constant"; import store from "./store"; //同步action,就是指action的值为object类型的一般对象 export const createIncrementAction = data => ({type: INCREMENT, data}) export const createDecrementAction = data => ({type: DECREMENT, data}) //所谓的异步action,就是指action的值为函数,需要使用一个中间插件, // 异步action中一般都会调用同步action,异步action不是必须要用的 export const createIncrementAsyncAction = (data, time) => { //返回的是一个函数 return () => { setTimeout(() => { store.dispatch(createIncrementAction(data)) }, time) } }
/*
* 该模块是用于定义action对象中type类型的常量值,
* 便于管理的同时,当值程序员单词写错,降低单词拼写出错率*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
//1、引入容器里面的CountContainer组件
import {CountContainer} from "./containers/count";
import './App.css';
function App() {
return (
<div className="App">
<CountContainer/>
</div>
);
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom/client';
import store from "./redux/store";
import {Provider} from "react-redux"
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
/*Provider让所有组件都可以得到state数据*/
<Provider store={store}>
<App/>
</Provider>
);
将UI组件和容器组件结合到一起
import {connect} from "react-redux"; import React, {Component} from 'react'; import {createIncrementAction, createDecrementAction, createIncrementAsyncAction} from "../../redux/count_action"; //定义UI组件 class Count extends Component { increment = () => { const {value} = this.selectNumber; this.props.jia(value * 1) } decrement = () => { const {value} = this.selectNumber; this.props.jian(value * 1) } //奇数再加 incrementIfOdd = () => { const {value} = this.selectNumber; if (this.props.count % 2 !== 0) { this.props.jia(value * 1) } } //异步加 incrementAsync = () => { const {value} = this.selectNumber; this.props.jiaAsync(value * 1, 500) } render() { console.log('UI组件', this.props); return ( <div> <h1>当前求和为:{this.props.count}</h1> <select ref={c => this.selectNumber = c}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select><br/><br/> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button> </div> ) } } export const CountContainer = connect( state => ({count: state}), { jia: createIncrementAction, jian: createDecrementAction, jiaAsync: createIncrementAsyncAction } )(Count)
效果:
文件目录:
containers/count/index.jsx
import {connect} from "react-redux"; import React, {Component} from 'react'; import {createIncrementAction, createDecrementAction, createIncrementAsyncAction} from "../../redux/actions/count"; class Count extends Component { increment = () => { const {value} = this.selectNumber; this.props.increment(value * 1) } decrement = () => { const {value} = this.selectNumber; this.props.decrement(value * 1) } incrementIfOdd = () => { const {value} = this.selectNumber; if (this.props.count % 2 !== 0) { this.props.increment(value * 1) } } incrementAsync = () => { const {value} = this.selectNumber; this.props.incrementAsync(value * 1, 500) } render() { console.log('UI组件', this.props); return ( <div> <h1>我是count组件</h1> <h1>当前求和为:{this.props.count}</h1> <h1>下方组件总人数为:{this.props.personTotal}</h1> <select ref={c => this.selectNumber = c}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select><br/><br/> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button> </div> ) } } export const CountContainer = connect( state => ({ count: state.countReducer, personTotal: state.personReducer.length }), { increment: createIncrementAction, decrement: createDecrementAction, incrementAsync: createIncrementAsyncAction } )(Count)
containers/person/index.jsx
import React, {Component} from 'react'; import {nanoid} from "nanoid" import {connect} from "react-redux"; import {createAddPersonAction} from "../../redux/actions/person" class Person extends Component { addPerson = () => { const name = this.nameNode.value; const age = this.ageNode.value; const personObj = {id: nanoid(), name, age}; console.log(personObj); this.props.addOnePerson(personObj); this.nameNode.value = ""; this.ageNode.value = ""; } render() { return ( <div> <h1>我是person组件</h1> <h1>上方组件的和为:{this.props.sum}</h1> <input ref={c => this.nameNode = c} type="text" placeholder="输入名字"/> <input ref={c => this.ageNode = c} type="text" placeholder="输入年龄"/> <button onClick={this.addPerson}>添加</button> <ul> {this.props.person.map((item) => { return (<li key={item.id}>名字:{item.name}----年龄:{item.age}</li>) })} </ul> </div> ) } } export const PersonContainer = connect( state => ({ person: state.personReducer, sum: state.countReducer }),//映射状态 {addOnePerson: createAddPersonAction} )(Person)
redux/actions/count.js
import {INCREMENT, DECREMENT} from "../constant";
import store from "../store";
export const createIncrementAction = data => ({type: INCREMENT, data})
export const createDecrementAction = data => ({type: DECREMENT, data})
export const createIncrementAsyncAction = (data, time) => {
return () => {
setTimeout(() => {
store.dispatch(createIncrementAction(data))
}, time)
}
}
redux/actions/person.js
import {ADD_PERSON} from "../constant";
//创建增加一个人的动作对象
export const createAddPersonAction=personObj=>({type:ADD_PERSON,data:personObj})
redux/reducers/count.js
import {INCREMENT,DECREMENT} from "../constant"; function countReducer(preState = 7, action) { console.log(preState, action); const {type, data} = action; switch (type) { case INCREMENT://加 return preState + data; case DECREMENT://减 return preState - data; default: return preState } } export default countReducer
redux/reducers/person.js
import {ADD_PERSON} from "../constant"
export default function personReducer(prevState = [{id: "001", name: "tom", age: 12}], action) {
const {type, data} = action;
switch (type) {
case ADD_PERSON:
return [data, ...prevState];
default:
return [...prevState]
}
}
redux/reducers/index.js:用于汇总多个reducer
//该文件用于汇总所有reducer
//引入combineReducers,用于汇总对个reducer
import {combineReducers} from "redux";
import countReducer from "./count";
import personReducer from "./person";
//合并reducer,保存的总状态是一个对象
const allReducer = combineReducers({
countReducer, personReducer
})
export default allReducer;
redux/costant.js
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
export const ADD_PERSON="addPerson"
redux/store.js
/*该文件专门用于暴露一个store对象,整个应用只有一个store对象*/
//1、引入createStore,专门用于创建redux中最为核心的store对象,applyMiddleware:执行中间件
import {createStore, applyMiddleware} from "redux";
//可以在浏览器中使用插件观察redux的状态变化
import {composeWithDevTools} from "redux-devtools-extension";
//2、引入汇总后的reducer
import allReducer from "./reducers";
//3、引入redux-thunk,用于支持异步action
import thunk from "redux-thunk";
//4、暴露store
export default createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)));
App.js
import {CountContainer} from "./containers/count";
import {PersonContainer} from "./containers/person";
import './App.css';
function App() {
return (
<div className="App">
<CountContainer/>
<hr/>
<PersonContainer/>
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import store from "./redux/store";
import {Provider} from "react-redux"
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
/*Provider包裹App,Provider让所有组件都可以得到state数据*/
<Provider store={store}>
<App/>
</Provider>
);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。