草庐IT

React(六) —— redux

旺仔好吃糖 2023-07-03 原文

🧁个人主页:个人主页

✌支持我 :点赞👍收藏🌼关注🧡

文章目录

⛳Redux

redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(state对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,一个新的对象就会被创建(使用actions和reducers)这样就可以进行数据追踪。

🍆redux定义

Redux 是一个使用叫做“action”的事件来管理和更新应用状态的模式和工具库。它以集中式Store(centralized store)的方式对整个应用中使用的状态进行集中管理,其规则确保状态只能以可预测的方式更新。

💐redux使用原则

🔎🔎🔎

  1. state以单一对象存储在store对象中
  2. state只读(每次都返回一个新的对象)
  3. 使用纯函数reducer执行state更新

🍰redux使用场景

🏸🏸🏸

  1. 同一个state需要在多个Component中共享
  2. 需要操作一些全局性的常驻Component,如Tooltips等
  3. 太多props需要在组件树中传递,其中大部分只是为了传给子组件
  4. 业务太复杂导致Component文件太大,可以考虑将业务逻辑拆出来放到Reducer中

🧊redux工作流程

📢📢📢

  1. 组件通过dispatch方法触发Action(type+payload载荷)
  2. Store接收Action并将Action分发给Reducer
  3. Reducer根据Action类型对状态进行更改并将更改后的状态返回给Store
  4. 组件订阅了Store中的状态,Store中的状态更新会同步到组件

🥫redux基本

创建store

redux文件夹下的store.js

//1.引入redux,
//2.createStore(reducer)
import {createStore} from 'redux'
const reducer = (preState,action)=>{
    return prevState
}
const store = createStore(reducer);
export default store

定义改变数据的actions,并在renducer函数中对对应的action作出不同的操作

//store.js 第二个参数为操作的actions
const reducer = (prevState={
    show:true,
    //...初始状态值
},action)=>{
    console.log(action);
    let newStare = {...prevState}
    switch(action.type){
        case 'hide-tabbar':
            newStare.show = false
            console.log(newStare.show);
            return newStare.show
        case 'show-tabbar':
            newStare.show = true
            console.log(newStare.show);
            return newStare.show
        default:
            return prevState
    }
}

离开或到达Detail页面,触发相应的actions

//Detail.js
import {show,hide} from '../../redux/actionCreator/TabbarActionCreator'

useEffect(()=>{
      //store.dispatch 通知
      store.dispatch(hide())
      return()=>{
        // console.log('destroy');
        store.dispatch(show())
      }
 },[])
.............................................
//actionCreator文件夹下TabbarActionCreator.js
function hide(){
    return {
            type:'hide-tabbar'
    }
}
function show(){
    return {
            type:'show-tabbar',//必须有type值
        	//payload:'需要传的值'
    }
}
export {show,hide}

订阅store,更新状态到页面上

//App.js中
state = {
    isShow:store.getState()
  }
  //store.subcribe 订阅
  componentDidMount(){
    store.subscribe(()=>{
      console.log('app中订阅',store.getState());
      this.setState({
        isShow:store.getState().show
      })

    })
  }
  //store.subcreibe 订阅
  render() {
    return (
      <div>
        <MRouter>
           {this.state.isShow && <Tabbar></Tabbar>}
        </MRouter>
      </div>
    )
}

获得store中的状态,根据状态的不同来控制Tabbar的显示或隐藏

🍸补充(actioncreator)

action creator是一个函数,用于生成一个action对象,他接受一个或多个参数(任何类型的数据),但是必须在action对象中有一个type属性:描述操作的类型。action creator函数返回一个对象,该对象是一个action,这个action对象包含了描述操作的数据

function addTodo(text){
	return{
		type:'add_todo'
	}
}
..............................
store.dispatch(addTodo())

上述:addTodo是一个action creator函数,它接受一个text参数并返回一个包含type和text属性的action对象。在Redux中,我们可以使用dispatch函数将这个action对象发送到store中,以便更新store状态。

🍫redux核心

  • getState:获取状态

    store.getState()
    
  • subscribe:订阅状态

    store.subscribe(()=>{})
    
  • dispatch:触发Action

    store.dispatch({type:'description...'})
    

reducer合并

🚀如果不同的action所处理的属性之间没有联系,我们可以把Reducer函数拆分。不同的函数负责处理不同属性,最终把他们合并成一个大的Reducer,并且抛出在store内的文件中引入。

redux文件夹下CityReducer.js

创建多个reducer,分别管理不同的数据

const CityReducer = (prevState={
    cityName:'北京'
},action)=>{
    let newStare = {...prevState}
    switch(action.type){
        case 'change-city':
            newStare.cityName = action.payload
            return newStare
        default:
            return prevState
    }
}
export default CityReducer

store.js

使用combinReducers方法合并多个Reducer。combinReducers方法可以吧多个reducer合并成一个reducer,以便在创建store实例时使用

import {combineReducers, createStore} from 'redux'
import CityReducer from './reducers/CityReducer';
import TabbarReducer from './reducers/TabbarReducer';
const reducer = combineReducers({
    CityReducer,
    TabbarReducer
})
const store = createStore(reducer);
export default store

redux中间件

在redux里,action仅仅是携带了数据的普通js对象,action creator返回的值是这个action类型的对象,然后通过store.dispatch()进行分发。同步的情况下一切都很完美,但是reducer无法处理异步的情况。

那么我们就需要action和reducer中间架起一座桥梁来处理异步。这就是middleware

redux-thunk

作用

🚒让我们的action创建函数不仅仅返回一个action对象,也可以返回一个函数,这个函数会接受dispatch和getState两个参数,我们可以在函数内部进行 异步操作 ,然后再通过dispatch发出一个新的action对象,来更新应用的状态

安装redux-thunk

npm i --save react-thunk

引入

import {applyMiddleware, combineReducers, createStore} from 'redux'
import reactThunk from 'redux-thunk'
const reducer = combineReducers({
    .....
})
const store = createStore(reducer,applyMiddleware(reactThunk));
export default store

使用方法

import getCinemsListAction from '../redux/actionCreator/getCinemsListAction'
store.dispatch(getCinemsListAction())
...............................
import axios from "axios"
function getCinemasListAction(){
   return(dispatch)=>{
    axios({
     ........
    }).then(res=>{
        console.log(res.data.data.cinemas);
        dispatch({
              type:'change-list',
              payload:res.data.data.cinemas
        })
    })
   
   }
}
export default getCinemasListAction

注意:

当我们使用react-thunk中间件时,他会判断action是否为函数,如果是函数就执行这个函数,并在函数内部发出一个新的action对象,若不是则按照正常进行

取消订阅

 //订阅
    var unsubcribe=store.subscribe(()=>{
    })
    return ()=>{
      //取消订阅
      unsubcribe()
    }
  },[])

redux-promise

安装redux-promise

npm i redux-promise

引入

import {applyMiddleware, combineReducers, createStore} from 'redux'
import reactThunk from 'redux-thunk'
import reactPromise from 'redux-promise'
const reducer = combineReducers({
    ....
})
const store = createStore(reducer,applyMiddleware(reactThunk,reactPromise));
export default store

使用方法

import getCinemsListAction from '../redux/actionCreator/getCinemsListAction'
store.dispatch(getCinemsListAction())
...............................
import axios from "axios"
async function getCinemasListAction(){
   var list = await axios({
        ......
    }).then(res=>{
       return{
        type:'change-list',
        payload://res.data.data.cinemas
       }
    })
    return list
 }
export default getCinemasListAction

有关React(六) —— redux的更多相关文章

  1. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  2. ruby - 单个 EventMachine react 器中的多个服务器 - 2

    是否可以在单个事件机器中运行多个服务器?我的意思是,多个服务可以由一个客户端连接同时使用。例如,登录服务器对用户进行身份验证,然后用户可以同时使用聊天室和简单的游戏,例如带有单个客户端套接字的跳棋?或者我是否需要为每个服务使用多个事件机器react器? 最佳答案 我试过了,它正在工作:#!/usr/bin/envrubyrequire'eventmachine'moduleEchoServerdefpost_initputs"--someoneconnectedtotheechoserver!"enddefreceive_datad

  3. React通过classnames库添加类 - 2

    React添加Class的方式在vue中添加class是一件非常简单的事情:你可以通过传入一个对象,通过布尔值决定是否添加类:button:class="{active:isFlag,aaa:true}">按钮button>你也可以传入一个数组:h2:class="['aaa','bbb']">HelloVueh2>h2:class="[className1,className2]">HelloVueh2>甚至是对象和数组混合使用:h2:class="['aaa',{active:isFlag}]">HelloVueh2>而在React中就相对繁琐了,React在JSX给了我们开发者足够多的灵

  4. 如何使React Router V4路由与React Transition Group(低级API)一起使用 - 2

    从ReactRouterV3过渡到V4后,我再也无法使ReactTransition组低级API工作。React路由器的文档显示了与CSS动画相关的高级API的示例,这些示例与低水平的JS风味不起作用。任何人都设法或知道让这个工作?看答案已经一个月了,所以我想您找到了自己的出路,但可能会对他人有所帮助。我创建了这个:https://www.npmjs.com/package/reeact-router-v4-transition在我遇到同样的问题之后。它在开关组件中提供了一种过渡组。从将开关更改为TransitionSwitch的Appart,它不需要大幅度更改。我将在接下来的几天(可能是星期

  5. javascript - 使用 React-Router 在路由之间传递 props - 2

    是在React-Router(1.0.0-rc)url参数中的路由之间传递数据的唯一方法吗?我有一个组件A,它使用Historymixin,并且有一个事件处理程序,该事件处理程序发出服务器请求,然后调用that.history.pushState(null,'/B');以过渡到路由B由组件B处理。现在,我想将服务器返回的一些数据作为Prop(例如“登录成功”)传递给组件B,或者以某种方式影响B的状态,但我找不到任何说明这是可能的。有什么办法可以做到这一点,还是我需要将其作为url参数传递? 最佳答案 你有两个选择:将数据作为查询参数

  6. javascript - react : input validation - 2

    我最近开始使用React,我遇到了输入验证问题。例如,它只是通过指令在另一个框架中作为Angular.js实现。经过一番研究,我发现newforms库,看起来像是当前开箱即用的最佳解决方案。但它非常重,不确定当前是否支持它(最后一次更新是7个月前)。另一种方法是将事件从父表单发送到其子输入,并在每个子输入上调用验证方法。但我找不到每个人都试图发明自己的东西的最佳实践,因此你需要自己写一些东西。表单验证的最佳解决方案是什么?React架构/框架(Flux/Redux)是否提供任何解决方案?谢谢, 最佳答案 我最近在React中使用了一

  7. javascript - 在单击事件上运行 AJAX 调用 - 使用 React.js - 2

    我正在创建一个网络应用程序,该应用程序将根据用户点击的城市对OpenWeatherAPI进行AJAX调用以获取城市的天气数据。我的前端使用React,后端使用Node.js/Express-但我无法正确设置如何根据用户的点击进行API调用。如何重构我的代码以使其基于点击?这是我目前所拥有的(JSBIN:http://bit.ly/1WedsL2)——目前硬编码为“London”:vardata=[{name:"London"},{name:"Tokyo"},{name:"NYC"}];varMusicBox=React.createClass({render:function(){re

  8. javascript - 在 React Native 中查看组件层次结构 - 2

    调试React网站时,我可以使用ReactDeveloperTools查看组件层次结构:我如何在ReactNative中做同样的事情?rageshake菜单包含一个“检查器”,但它似乎只能让我通过点击它来检查单个元素-我看不到任何浏览完整组件层次结构的方法。 最佳答案 不幸的是,从react-native0.12版本开始,Devtools的“React”选项卡不再起作用。这是aknownissue.有一个quiteactivediscussiononGithub已经开放了一段时间,但还没有解决方案。更新Devtools“React”

  9. javascript - 在 React.JS 中禁用右键单击 - 2

    如何在ReactJS中禁用Canvas中的右键单击。这是我尝试过但仍然无效的方法:letCanvas={e.preventDefault();returnfalse;}}height={500}width={500}ref="canvas"/>;浏览器控制台中也会显示警告。Warning:Returningfalsefromaneventhandlerisdeprecatedandwillbeignoredinafuturerelease.Instead,manuallycalle.stopPropagation()ore.preventDefault(),asappropriate.

  10. javascript - react 路由器中的层次结构 - 2

    我正在学习React,我尝试创建一些路由,我的入口点上有这段代码:importReactfrom'react';importReactDOMfrom'react-dom';import{Router,Route,IndexRoute,Link,IndexLink,browserHistory}from'react-router';importAppfrom'./app/Components/AppComponent';importSupervisoryReportfrom'./app/Components/SupervisoryReportComponent';importTopmen

随机推荐