在React中使用Redux解决的问题小结_第1页
在React中使用Redux解决的问题小结_第2页
在React中使用Redux解决的问题小结_第3页
在React中使用Redux解决的问题小结_第4页
在React中使用Redux解决的问题小结_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第在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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论