一、区别
redux: 第三方数据状态管理的库
react-redux: 封装了 redux 的一些操作,使用更方便
二、redux 基本使用
1、安装
npm i redux -S
2、了解 redux 中的常见概念
state: 存储共享 store 数据的变量action: 一个对象,表示要改变 store 数据的操作,类似 { type: 'ADD', payload: '参数' }store.getState():获取存储在 store 中的数据store.dispatch(): 执行一个改变 store 共享数据操作,里面传action这个对象store.subscribe(): 在组件中监听 store 共享数据变化
点击下载项目 ,直接本地运行
三、redux 项目demo
*1. 实现效果
增加的数据存入通过 redux 来存储,点击按钮 添加数据,并在组件中 获取数据列表, 并可点击进行 数据删除
2. 项目目录
3. 各文件代码
reduxDemo.jsx组件文件
import React from "react";
// 引入 定义好的 store
import store from "../redux-store";
import {
changeInputAction,
addItemAction,
deleteItemAction,
} from "../redux-store/actionCreator";
export default class ReduxDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '测试',
}
// 监听变化,更新视图
// store.subscribe(this.updateList)
}
// 更新视图
updatePage = () => {
// store.getState() 返回一个对象,将数据保存到 state
this.setState({
list: store.getState()?.list
})
}
componentDidMount() {
// 监听订阅,更新视图
let unsubscribe = store.subscribe(this.updatePage);
this.setState({
unsubscribe,
});
}
componentWillUnmount() {
// 移除订阅
this.state.unsubscribe();
}
// 输入框改变
inputChange = (e) => {
const changeAction = changeInputAction(e.target.value);
store.dispatch(changeAction);
};
// 添加到 list
add = () => {
const addAction = addItemAction();
if (store.getState()?.inputVal) {
store.dispatch(addAction);
}
};
// 删除
deleteItem = (index) => {
const deleteAction = deleteItemAction(index);
store.dispatch(deleteAction);
};
render() {
return (
<div>
<div>redux</div>
<input
value={store.getState()?.inputVal || ''}
onChange={this.inputChange}
type="text"
/>
<button onClick={this.add}>增加</button>
<ul>
{/* 也可直接通过 store.getState() 去使用 */}
{/* {store.getState()?.list?.map((item, index) => { */}
{this?.state?.list?.map((item, index) => {
return (
<button onClick={()=>{
this.deleteItem(index)
}} key={index}>
{item}
</button>
);
})}
</ul>
</div>
);
}
}
2.redux-store 文件夹下的 index.js ( store 的入口文件 )
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from 'redux-logger';
import thunk from 'redux-thunk'
// 引入定义的 reducer 纯函数
import { reducer } from './reducer';
// 加入中间件,可打印 store 的更新变化
const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk, logger)));
// 启用 react-redux 浏览器扩展 window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
// const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export default store;
3.redux-store 文件夹下的 reducer.jsx ( 状态处理器函数,根据不同 action类型 获取最新的 state 对象, 并返回它 )
import { CHANGE_INPUT, ADD_ITEM, DELETE_ITEM } from "./actionTypes";
// 纯函数, 根据不同的 action 返回新的 state
export const reducer = (state = { inputVal: 0, list: [] }, action) => {
if (action.type === CHANGE_INPUT) {
return {
...state,
inputVal: action.value
}
}
if (action.type === ADD_ITEM) {
let newState = JSON.parse(JSON.stringify(state));
newState.list?.push(newState.inputVal);
newState.inputVal = ""; // 清空输入框
return newState;
}
if (action.type === DELETE_ITEM) {
let newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
};
4.redux-store 文件夹下的 actionTypes.jsx ( 定义的 action 类型,用常量定义 )
// 定义常量
export const CHANGE_INPUT = 'changeInput';
export const ADD_ITEM = 'addItem';
export const DELETE_ITEM = 'deleteItem';
5.redux-store 文件夹下的 actionCreator.jsx ( 根据 action 类型,生成不同的 action 对象 )
// 创建 action 对像的方法
import { CHANGE_INPUT, ADD_ITEM, DELETE_ITEM } from "./actionTypes";
export const changeInputAction = (value)=> {
return {
type: CHANGE_INPUT,
value
}
}
export const addItemAction = () => {
return {
type: ADD_ITEM
}
}
export const deleteItemAction = (index) => {
return {
type: DELETE_ITEM,
index
}
}
6.根 index.js 文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux-store';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
7.根 App.js 文件
import ReduxDemo from './redux-demo/reduxDemo';
import ReactReduxDemo from './react-redux-demo/reactReduxDemo';
import './App.css'
function App() {
return (
<div className="App">
<ReduxDemo />
<ReactReduxDemo />
</div >
);
}
export default App;
四、redux + react-redux 项目demo
1、安装
npm i redux react-redux -S
2、实现效果 (和上面一致)
3.目录
4. 各文件代码
reactReduxDemo.jsx组件文件
import React from "react";
import { connect } from "react-redux";
import Son from './son';
import {
changeInputAction,
addItemAction,
deleteItemAction,
} from "../react-redux-store/actionCreator";
class ReactReduxDemo extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
// 输入框改变
inputChange = (e) => {
// const changeAction = changeInputAction(e.target.value);
// store.dispatch(changeAction);
this.props.customChangeInput(e.target.value);
};
// 添加到 list
add = () => {
// const addAction = addItemAction();
// if (store.getState()?.inputVal) {
// store.dispatch(addAction);
// }
if(this.props.displayInputVal) {
this.props.customAddItem();
}
};
// 删除
deleteItem = (index) => {
// const deleteAction = deleteItemAction(index);
// store.dispatch(deleteAction);
this.props.customDeleteItem(index)
};
render() {
return (
<div>
<div>react-redux</div>
<input
value={this.props?.displayInputVal || ''}
onChange={this.inputChange}
type="text"
/>
<button onClick={this.add}>增加</button>
<ul>
{this.props?.displayList?.map((item, index) => {
return (
<button onClick={()=>{
this.deleteItem(index)
}} key={index}>
<div>{item}</div>
</button>
);
})}
</ul>
{/* Son组件 */}
<Son />
</div>
);
}
}
const mapStateToProps = (state) => {
return {
displayInputVal: state?.inputVal,
displayList: state?.list,
};
};
const mapDispatchToProps = (dispatch) => {
return {
customChangeInput: (inputVal) => {
// 调用 dispatch
dispatch(changeInputAction(inputVal));
},
customAddItem: () => {
// 调用 dispatch
dispatch(addItemAction());
},
customDeleteItem: (deleteIndex) => {
dispatch(deleteItemAction(deleteIndex));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ReactReduxDemo);
son.jsx组件
import React from 'react';
import { connect } from 'react-redux';
import {
deleteItemAction,
} from '../react-redux-store/actionCreator'
class Son extends React.Component {
// 删除
deleteItem = (index) => {
this.props.customDeleteItem(index)
}
render() {
return (
<div>
<h3>子组件展示</h3>
<div>
{this.props?.displayList?.map((item, index) => {
return (
<button onClick={()=>{
this.deleteItem(index)
}} key={index}>
<div>{item}</div>
</button>
);
})}
</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
displayList: state?.list
}
}
const mapDispatchToProps = (dispatch) => {
return {
customDeleteItem: (deleteIndex)=> {
dispatch(deleteItemAction(deleteIndex))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Son)
react-redux-store和redux-store中的四个文件一致
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from 'redux-logger';
import thunk from 'redux-thunk'
// 引入定义的 reducer 纯函数
import { reducer } from './reducer';
// 加入中间件,可打印 store 的更新变化
// const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk, logger)));
// 启用 react-redux 浏览器扩展 window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export default store;
五、主要区别点
redux需要在组件中调用store.subscribe()来监听 数据变化, 而react-redux有 给根组件 提供Provider,使得所有组件 可直接获取到 store 中的最新数据
import { Provider } from 'react-redux';
<Provider store={store}>
<App />
</Provider>
react-redux直接通过connect函数包裹 自定义的组件, 在mapStateToProps和mapDispatchToProps中处理后,可直接在组件中 通过this.props.变量名/方法名获取 store 中的变量,执行更新(派发)操作
const mapStateToProps = (state) => {
return {
displayInputVal: state?.inputVal,
displayList: state?.list,
};
};
const mapDispatchToProps = (dispatch) => {
return {
customChangeInput: (inputVal) => {
// 调用 dispatch
dispatch(changeInputAction(inputVal));
},
customAddItem: () => {
// 调用 dispatch
dispatch(addItemAction());
},
customDeleteItem: (deleteIndex) => {
dispatch(deleteItemAction(deleteIndex));
},
};
};
// 通过 connect 连接
export default connect(mapStateToProps, mapDispatchToProps)(ReactReduxDemo);