版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第在React中使用Redux解决的问题小结目录在React中使用Redux解决的问题在React项目中加入Redux的好处React+Redux安装ReduxReact中Redux的工作流程React计数器案例使用ReduxProvide组件connect方法使用bindActionCreators方法继续简化代码重构为Action传递参数Redux弹出框初始化静态内容添加默认隐藏状态定义操作按钮衍生的问题拆分合并reducer拆分合并调整组件
在React中使用Redux解决的问题
在React项目中未加入Redux时的问题
在React中组件通信的数据流是单向的,顶层组件可以通过props属性向下层组件传递数据,而下层组件不能直接向上层组件传递数据。要实现下层组件修改上层组件的数据,需要上层组件传递修改数据的方法到下层组件。当项目越来越大的时候,组件之间传递数据以及传递修改数据的方法变得越来越困难。
在React项目中加入Redux的好处
使用Redux管理数据,由于Store独立于组件,使得数据管理独立于组件,解决了组件与组件之间传递数据困难的问题。
React+Redux安装Redux
在react项目中使用redux要下载两个模块
npminstallreduxreact-redux
React中Redux的工作流程
在React中Redux的工作流程有些变化:
组件通过dispatch方法触发ActionStore接收Action并将Action分发给ReducerReducer根据Action类型对状态进行更改并将更改后的状态返回给Store组件订阅了Store中的状态,Store中的状态更新会同步到组件
React计数器案例
React实现
创建项目安装模块
#创建项目(React17版本)
npxcreate-react-appmyapp
#安装redux
cdmyapp
npminstallredux
删掉无用的文件
├─src
│├─App.css
│├─App.test.js
│├─index.css
│├─logo.svg
│├─reportWebVitals.js
│└─setupTests.js
初步实现
//src/index.js
importReactfrom'react';
importReactDOMfrom'react-dom';
import{createStore}from'redux'
constinitialState={
count:0
functionreducer(state=initialState,action){
switch(action.type){
case'increment':
return{
count:state.count+1
case'decrement':
return{
count:state.count-1
default:
returnstate
conststore=createStore(reducer)
constincrement={type:'increment'}
constdecrement={type:'decrement'}
functionCounter(){
returndiv
button()=store.dispatch(increment)}+/button
span{store.getState().count}/span
button()=store.dispatch(decrement)}-/button
/div
store.subscribe(()={
ReactDOM.render(
React.StrictMode
Counter/
/React.StrictMode,
document.getElementById('root')
console.log(store.getState())
ReactDOM.render(
React.StrictMode
Counter/
/React.StrictMode,
document.getElementById('root')
使用Redux
开发时我们会把组件写在单独的文件中,如果将Counter组件单独提取,就无法访问store对象以及一些其它的问题,所以需要使用redux。
安装react-redux
npminstallreact-redux
react-redux用于让react和redux完美结合,它仅仅提供两个内容:
Provider组件它可以将创建出来的store放到全局,允许所有组件访问可以解决将组件存储在单独文件中时,访问storeconnect方法connect方法会帮助订阅store,当store中的状态发生变化,会重新渲染组件解决了需要手动订阅更新组件状态connect方法可以获取store中的状态,映射到组件的props属性中connect方法可以获取dispatch方法,组件可以通过props.dispatch访问
Provide组件
Provider组件要包裹项目中所有的组件,也就是应该被放在最外层组件上Provider通过store属性接收创建的store对象
connect方法
首先调用connect方法第一个参数是一个函数函数接收的第一个参数,即组件中的状态state函数要返回一个对象,该对象定义的属性都会映射到组件的props属性中第二个参数也是一个函数函数接收的第一个参数,即dispatch方法函数要返回一个对象,可以定义触发Action的方法,它们同样会被映射到组件的props属性中返回一个方法继续调用返回的方法,并传递当前的组件
修改代码
//src/index.js
importReactfrom'react';
importReactDOMfrom'react-dom';
import{createStore}from'redux'
importCounterfrom'./components/Counter'
import{Provider}from'react-redux'
constinitialState={
count:0
functionreducer(state=initialState,action){
switch(action.type){
case'increment':
return{
count:state.count+1
case'decrement':
return{
count:state.count-1
default:
returnstate
conststore=createStore(reducer)
ReactDOM.render(
//通过provider组件将store放在了全局,供所有组件可以访问
React.StrictMode
Providerstore={store}
Counter/
/Provider
/React.StrictMode,
document.getElementById('root')
提取的Counter组件
//src/components/Counter.js
import{connect}from'react-redux'
functionCounter(props){
returndiv
button()=props.dispatch({type:'increment'})}+/button
span{props.count}/span
button()=props.dispatch({type:'decrement'})}-/button
/div
constmapStateToProps=state=({
count:state.count
exportdefaultconnect(mapStateToProps)(Counter)
使用connect第二个参数简化组件
//src/components/Counter.js
import{connect}from'react-redux'
functionCounter({count,increment,decrement}){
returndiv
buttonincrement}+/button
span{count}/span
buttondecrement}-/button
/div
constmapStateToProps=state=({
count:state.count
constmapDispatchToProps=dispatch=({
increment(){
dispatch({type:'increment'})
decrement(){
dispatch({type:'decrement'})
exportdefaultconnect(mapStateToProps,mapDispatchToProps)(Counter)
使用bindActionCreators方法继续简化
触发Action的方法increment和decrement的内容基本是一样的,redux提供bindActionCreators方法生成一个函数,来简化这种重复性代码。
参数actionCreators:对象或返回对象的函数key是生成函数的名称value是一个返回Action的函数dispatch:需传递Store的dispatch方法返回一个对象,同connect接收的第二个参数
//src/components/Counter.js
import{connect}from'react-redux'
import{bindActionCreators}from'redux'
functionCounter({count,increment,decrement}){
returndiv
buttonincrement}+/button
span{count}/span
buttondecrement}-/button
/div
constmapStateToProps=state=({
count:state.count
constmapDispatchToProps=dispatch=({
...bindActionCreators({
increment(){
return{type:'increment'}
decrement(){
return{type:'decrement'}
},dispatch)
exportdefaultconnect(mapStateToProps,mapDispatchToProps)(Counter)
此时还没有达到简化的效果,可以将actionCreators提取到单独的文件中。
//src\store\actions\counter.action.js
exportconstincrement=()=({type:'increment'})
exportconstdecrement=()=({type:'decrement'})
//src/components/Counter.js
import{connect}from'react-redux'
import{bindActionCreators}from'redux'
import*ascounterActionsfrom'../store/actions/counter.action'
functionCounter({count,increment,decrement}){
returndiv
buttonincrement}+/button
span{count}/span
buttondecrement}-/button
/div
constmapStateToProps=state=({
count:state.count
constmapDispatchToProps=dispatch=bindActionCreators(counterActions,dispatch)
exportdefaultconnect(mapStateToProps,mapDispatchToProps)(Counter)
代码重构
为了继续演示Redux的相关内容,将与Redux相关的代码从src/index.js中抽离出去,让项目结构更加合理。
将reducer函数抽离到一个文件中将创建store的代码手里到一个文件中将Actions的type抽象成模块中的成员,好处是:编辑器有提示,避免写错
编辑器自动插入模块引入的代码
将Actions的type抽象成模块中的成员
//src\store\actions\counter.action.js
import{DECREMENT,INCREMENT}from"../const/counter.const"
exportconstincrement=()=({type:INCREMENT})
exportconstdecrement=()=({type:DECREMENT})
将reducer函数抽离到一个文件中
//src\store\reducers\counter.reducer.js
import{DECREMENT,INCREMENT}from"../const/counter.const"
constinitialState={
count:0
functionreducer(state=initialState,action){
switch(action.type){
caseINCREMENT:
return{
count:state.count+1
caseDECREMENT:
return{
count:state.count-1
default:
returnstate
exportdefaultreducer
将创建store的代码手里到一个文件中
//src\store\index.js
import{createStore}from'redux'
importreducerfrom'./reducers/counter.reducer'
exportconststore=createStore(reducer)
修改后的src/index.js
//src/index.js
importReactfrom'react'
importReactDOMfrom'react-dom'
importCounterfrom'./components/Counter'
import{Provider}from'react-redux'
import{store}from'./store'
ReactDOM.render(
//通过provider组件将store放在了全局,供所有组件可以访问
React.StrictMode
Providerstore={store}
Counter/
/Provider
/React.StrictMode,
document.getElementById('root')
)
为Action传递参数
当前计数器对数字进行递增/减的数值为1,现在通过给Action传递参数,允许自定义数值。
传递参数:调用触发Action函数的时候传递参数接收参数:返回Action的函数接收参数,添加到返回的Action对象中处理参数:reducer函数处理的时候,可以从action对象获取这个参数,进行处理
传递参数:
//src/components/Counter.js
functionCounter({count,increment,decrement}){
//修改Counter组件中调用incrementdecrement函数的地方
return(
div
button()=increment(5)}+/button
span{count}/span
button()=decrement(5)}-/button
/div
接收参数:
//src\store\actions\counter.action.js
import{DECREMENT,INCREMENT}from"../const/counter.const"
exportconstincrement=payload=({type:INCREMENT,payload})
exportconstdecrement=payload=({type:DECREMENT,payload})
处理参数:
//src\store\reducers\counter.reducer.js
import{DECREMENT,INCREMENT}from"../const/counter.const"
constinitialState={
count:0
functionreducer(state=initialState,action){
switch(action.type){
caseINCREMENT:
return{
count:state.count+action.payload
caseDECREMENT:
return{
count:state.count-action.payload
default:
returnstate
exportdefaultreducer
Redux弹出框
在页面中显示两个按钮:
显示:显示弹出框隐藏:隐藏弹出框
初始化静态内容
Modal组件
//src\components\Modal.js
functionModal(){
conststyles={
width:200,
height:200,
position:'absolute',
left:'50%',
top:'50%',
marginLeft:-100,
marginTop:-100,
backgroundColor:'skyblue'
return(
div
button显示/button
button隐藏/button
div>
修改src/index.js
//src/index.js
importReactfrom'react'
importReactDOMfrom'react-dom'
importAppfrom'./App'
import{Provider}from'react-redux'
import{store}from'./store'
ReactDOM.render(
//通过provider组件将store放在了全局,供所有组件可以访问
React.StrictMode
Providerstore={store}
App/
/Provider
/React.StrictMode,
document.getElementById('root')
)
修改src/App.js
//src\App.js
importCounterfrom'./components/Counter'
importModalfrom'./components/Modal'
functionApp(){
return(
div
Counter/
Modal/
/div
exportdefaultApp
添加默认隐藏状态
在reducer中添加显示状态的属性
//src\store\reducers\counter.reducer.js
import{DECREMENT,INCREMENT}from"../const/counter.const"
constinitialState={
count:0,
showStatus:false
functionreducer(state=initialState,action){...}
exportdefaultreducer
在组件中使用状态
//src\components\Modal.js
import{connect}from'react-redux'
functionModal({showStatus}){
conststyles={
width:200,
height:200,
position:'absolute',
left:'50%',
top:'50%',
marginLeft:-100,
marginTop:-100,
backgroundColor:'skyblue',
display:showStatus'block':'none'
return(
div
button显示/button
button隐藏/button
div>
定义操作按钮
定义Action的type
//src\store\const\modal.const.js
exportconstSHOWMODAL='showModal'
exportconstHIDEMODAL='hideModal'
定义生成Action的函数
//src\store\actions\modal.actions.js
import{HIDEMODAL,SHOWMODAL}from"../const/modal.const"
exportconstshow=()=({type:SHOWMODAL})
exportconsthide=()=({type:HIDEMODAL})
创建触发Action的方法并使用
//src\components\Modal.js
import{connect}from'react-redux'
import{bindActionCreators}from'redux'
import*asmodalActionsfrom'../store/actions/modal.actions'
functionModal({showStatus,show,hide}){
conststyles={
width:200,
height:200,
position:'absolute',
left:'50%',
top:'50%',
marginLeft:-100,
marginTop:-100,
backgroundColor:'skyblue',
display:showStatus'block':'none'
return(
div
buttonshow}显示/button
buttonhide}隐藏/button
div>
修改reducer函数,处理变更:
//src\store\reducers\counter.reducer.js
import{DECREMENT,INCREMENT}from'../const/counter.const'
import{HIDEMODAL,SHOWMODAL}from'../const/modal.const'
constinitialState={
count:0,
showStatus:false
functionreducer(state=initialState,action){
switch(action.type){
caseINCREMENT:
//reducer返回的对象会替换store中的状态对象,所以要将其它状态也包含进去
return{
...state,
count:state.count+action.payload
caseDECREMENT:
return{
...state,
count:state.count-action.payload
caseSHOWMODAL:
return{
...state,
showStatus:true
caseHIDEMODAL:
return{
...state,
showStatus:false
default:
returnstate
exportdefaultreducer
注意:reducer返回的对象会替换store中的状态对象,所以要将其它状态也包含进去
衍生的问题
在reducer函数中匹配了所有状态的变更,当项目越来越大,状态越来越多时,管理起来就很麻烦。
所以要将rreducer函数进行拆分。
拆分合并reducer拆分
将modal拆分出去
//src\store\reducers\modal.reducer.js
import{HIDEMODAL,SHOWMODAL}from'../const/modal.const'
constinitialState={
show:false
constreducer=(state=initialState,action)={
switch(action.type){
caseSHOWMODAL:
return{
...state,
showStatus:true
caseHIDEMODAL:
return{
...state,
showStatus:false
default:
returnstate
exportdefaultreducer
//src\store\reducers\counter.reducer.js
import{DECREMENT,INCREMENT}from'../const/counter.const'
constinitialState={
count:0,
functionreducer(state=initialState,action){
switch(action.typ
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年步态识别在机场安防中的应用
- T∕CAQI 330-2023 质量检验检测行业自律规范
- 车用汽油招聘考试试题及答案
- 2026年小学语文生僻字考试试题及答案
- 2025-2026学年四川眉山第一中学高二下学期期中语文诊断测试题 含答案
- 铁路试验钢筋考试试题及答案
- 楼盘期房预售保障承诺书7篇范文
- 软件工程师精通软件测试指导书
- 航空货运物流信息平台开发策略
- 农业种植合约履行安全防护责任书6篇
- 2025年课件-(已瘦身)2023版马原马克思主义基本原理(2023年版)全套教学课件-新版
- QCT1177-2022汽车空调用冷凝器
- 人教版数学小学五年级下册期末测试卷附答案(满分必刷)
- 学校收费调整应急预案
- 核电站反应堆控制棒驱动机构课件
- 2023新高考Ⅰ卷数学真题(原卷版)
- 大学生本科毕业后,先工作还是先考研辩论稿5篇汇编
- 职业技能大赛:中式烹调师(三级)理论知识考核要素细目表(征求意见稿)
- 国际航运管理课程设计
- 事业单位公开招聘人员政审表(样表)
- GB/T 42061-2022医疗器械质量管理体系用于法规的要求
评论
0/150
提交评论