为什么用react-redux?
- redux与react组件的代码耦合度太高
- 编码不够简洁
基本概念
React-Redux将所有组件分成两大类
UI组件
a.只负责 UI 的呈现,不带有任何业务逻辑
b.通过props接收数据(一般数据和函数)
c.不使用任何 Redux 的 API
d.一般保存在components文件夹下
容器组件
a.负责管理数据和业务逻辑,不负责UI的呈现
b.使用 Redux 的 API
c.一般保存在containers文件夹下
相关API
1.Provider
让所有组件都可以得到state数据
<Provider store={store}>
<App />
</Provider>2.connect()
用于包装 UI 组件生成容器组件
import { connect } from 'react-redux'
connect(
mapStateToprops,
mapDispatchToProps
)(Counter)3.mapStateToprops()
将外部的数据(即state对象)转换为UI组件的标签属性
const mapStateToprops = function (state) {
return {
value: state
}
}4.mapDispatchToProps()
将分发action的函数转换为UI组件的标签属性
简洁语法可以直接指定为actions对象或包含多个action方法的对象
下载包 npm install --save react-redux
优化redux:根据 React-Redux组件分类思想,将app.jsx从上一篇的redux内抽离出来
// app.jsx import { connect } from "react-redux"; // 引入action内的方法 import { increment, decrement } from "../redux/actions"; // 引入容器组件 import counter from "../components/counter"; export default connect( (state) => { // state为store内的count值 即0 console.log(state, "state"); // 将state状态传给counter组件 return { count: state }; }, // 将increment,decrement方法传给counter { increment, decrement } )(counter);
// counter.js内 // 导入 React 模块 import React, { Component } from "react"; import propTypes from "prop-types"; // 暴露并创建react类 export default class App extends Component { static propTypes = { count: propTypes.number.isRequired, increment: propTypes.func.isRequired, decrement: propTypes.func.isRequired, }; addCountFn = () => { this.props.increment(this.select.value * 1); }; delCountFn = () => { this.props.decrement(this.select.value * 1); }; incrementOddFn = () => { const { count } = this.props; if (count % 2 === 1) { this.props.increment(this.select.value * 1); } }; incrementAsyncFn = () => { setTimeout(() => { this.props.increment(this.select.value * 1); }, 1000); }; render() { const { count } = this.props; return ( <div> <h2>click {count} times</h2> <select ref={(select) => (this.select = select)}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button onClick={this.addCountFn}>+</button> <button onClick={this.delCountFn}>-</button> <button onClick={this.incrementOddFn}>increment if odd</button> <button onClick={this.incrementAsyncFn}>increment async</button> </div> ); } }
// index.js import React from "react"; import { createRoot } from 'react-dom/client'; import { Provider } from "react-redux"; import store from './redux/store' import App from "./containers/app"; createRoot(document.getElementById('root')).render( <Provider store={store} > <App /> </Provider> );;
上一篇问题:reducers.js如何暴露多个模块
// reducers.js import { COMMENT_ADD, COMMENT_DEL, COMMENT_INIT, INCREMENT, DECREMENT } from "./action-types"; import { combineReducers } from 'redux' const initCommentData = [] function comments (state = initCommentData, actions) { switch (actions.type) { // 添加方法 case COMMENT_ADD: return [actions.data, ...state] // 删除方法 case COMMENT_DEL: return state.filter((comment, index) => index !== actions.data) // 初始化评论 case COMMENT_INIT: return actions.data // 默认 default: return state } } function counter (state = 0, action) { switch (action.type) { case INCREMENT: return state += action.data case DECREMENT: return state -= action.data default: return state } } export default combineReducers( { comments, counter } )
暴露多个模块后,相应的组件 也要做修改
// app.jsx import React, { Component } from "react"; import { connect } from "react-redux"; import PropTypes from "prop-types"; import Add from "../../components/commentAdd/commentAdd"; import List from "../../components/commentList/commentList"; import { commentAdd, commentDel, commentAsync } from "../../redux/actions"; import "./app.css"; class App extends Component { static propTypes = { commentList: PropTypes.array.isRequired, commentAdd: PropTypes.func.isRequired, commentDel: PropTypes.func.isRequired, commentAsync: PropTypes.func.isRequired, }; componentDidMount() { const { commentAsync } = this.props; commentAsync(); } render() { const { commentList, commentAdd, commentDel } = this.props; return ( <div id="app"> <div> <header className="site-header jumbotron"> <div className="container"> <div className="row"> <div className="col-xs-12"> <h1>请发表对React的评论</h1> </div> </div> </div> </header> <div className="container"> <Add commentAdd={commentAdd} /> <List commentList={commentList} commentDel={commentDel} /> </div> </div> </div> ); } } export default connect((state) => // 此处为reducers修改后调整 ({ commentList: state.comments }), { commentAdd, commentDel, commentAsync } )(App);
// store.js 存储 状态变量 import { configureStore } from '@reduxjs/toolkit' import reducers from './reducers' // 根据comments函数创建store对象 const store = configureStore({ reducer: reducers }) console.log(store, 'store'); export default store
redux如何处理异步操作???
redux-thunk处理异步操作_FF_XM的博客-CSDN博客
redux基本概念