網(wǎng)站首頁 編程語言 正文
redux與react-redux
- 前言
- 一、redux和react-redux是啥?
- 二、redux使用步驟
- 1.引入庫
- 2.原理圖
- 原理圖釋義
- actions
- 1)含義
- 2)demo
- store.js
- 1)含義
- 2)demo
- reducer.js
- 1)含義
- 2)demo
- Count.jsx
- 1)含義
- 2)demo
- Person.jsx
- 三、redux開發(fā)者工具的使用
- 總結
前言
工作中Vue為主,React使用逐漸生疏,對redux僅達到會用的地步。偶爾遇到React項目,用到redux也就是把別人寫過的東西重寫一遍,最近有時間去B站白嫖了一下 React教程。寫個筆記記錄下!!!
一、redux和react-redux是啥?
redux是 JavaScript 狀態(tài)容器,提供可預測化的狀態(tài)管理,是一個獨立的庫可以搭配UI框架進行使用。
與redux稍加不同的是,react-redux是 React 的官方 Redux UI 綁定庫,可以訂閱 store、檢查更新數(shù)據(jù)和觸發(fā)重新渲染的過程可以變得更加通用和可復用。
簡單的說,react-redux最終還是使用redux去取數(shù)據(jù),不過是封裝一層方便使用redux的api。
相對于Vuex的簡單無腦操作,這兩個算是稍微麻煩一點的。不過后續(xù)阿里封裝了個hox,使用起來感覺簡單了很多。
二、redux使用步驟
1.引入庫
代碼如下(示例):
npm install react-redux
2.原理圖
原理圖釋義
1.所有的UI組件都應該包裹一個容器組件,他們是父子關系
2.容器組件是真正和redux打交道的,里面可以隨意的使用redux的api
3.UI組件不能使用任何redux的api
4.容器組件會傳給UI組件:1)redux中所保存的狀態(tài),2)用于操作狀態(tài)的方法
5.備注:容器給UI傳遞:狀態(tài)、操作狀態(tài)的方法,均通過props傳遞
actions
1)含義
Action 是把數(shù)據(jù)從應用傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來源。一般來說你會通過 store.dispatch() 將 action 傳到 store。
action返回的是Object類型的叫做同步action
action返回的是Function類型的叫做異步 action
異步action:
(1).明確:延遲的動作不想交給組件自身,想交給action
(2).何時需要異步action:想要對狀態(tài)進行操作,但是具體的數(shù)據(jù)靠異步任務返回(非必須)
(3).具體編碼:
1).cnpm i redux-thunk,并配置在store中,//行駛轉換程序
2).創(chuàng)建action的函數(shù)不再返回一般對象,而是一個函數(shù),該函數(shù)中寫異步任務
3).異步任務有結果后,分發(fā)一個同步的action去真正的操作數(shù)據(jù)
(4).備注:異步action不是必須要寫的,完全可以自己等待異步任務的結果再去分發(fā)同步action
2)demo
//redux文件夾下新建constant.js文件
/* 該模塊適用于定義action對象中type類型的常量值
目的只有一個:便于管理的同時防止單詞寫錯
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const SET_OPERATOR = 'setOperator'
//redux文件夾下新建action文件夾
//action下新建count_actions.js
/*
該文件專門為Count組件生成求和count_actions對象
*/
import {INCREMENT, DECREMENT} from '../constant'
export const incrementAction = (data) => ({ type: INCREMENT, data })//同步action
//同步action,就是指action的返回值為Object類型的一般對象
export function decrementAction(data){
return {
type: DECREMENT,
data
}//返回的是一個對象,普通數(shù)據(jù)類型,同步action,返回對象為異步
}
//異步action,就是指action的返回值為函數(shù)
//異步action中,一般都會調用同步action,異步action不是必須要用的
export const incrementAsyncAction = (data, time) => {
return (dispatch)=>{//返回對象為異步action
setTimeout(()=>{
dispatch(incrementAction(data))
}, time)
}
}
//action下新建user_action.js
import { SET_OPERATOR } from '../constant'
export function setOperator(data){
return{
type: SET_OPERATOR,
data,
}
}
store.js
1)含義
store是一個狀態(tài)管理器,是一個倉庫,存儲公共的狀態(tài)數(shù)據(jù)。Redux 應用只有一個單一的 store
1)引入redux中的createStore函數(shù),創(chuàng)建一個store
2)createStore調用時要傳入一個為其服務的reducer
3)記得暴露store對象
4) redux只負責管理狀態(tài),至于狀態(tài)的改變驅動著頁面的展示要靠我們自己寫
2)demo
//redux文件夾新建store.js
//引入creacteStore,專門用于創(chuàng)建redux中最核心的store對象,applyMiddleware執(zhí)行中間件
import { legacy_createStore as createStore, applyMiddleware} from "redux";
//引入redux-thunk用于支持異步action
import thunk from 'redux-thunk'
//引入為組件服務的reducer
import rootReducers from './reducers'
const store = createStore(rootReducers, applyMiddleware(thunk))
//暴露出去
export default store
reducer.js
1)含義
Reducers 指定了應用狀態(tài)的變化如何響應 actions 并發(fā)送到 store 的,記住 actions 只是描述了有事情發(fā)生了這一事實,并沒有描述應用如何更新 state。
1)reducer的本質是一個函數(shù),接收:preState,action,發(fā)布加工后的狀態(tài)
2)reducer有兩個作用:初始狀態(tài),加工狀態(tài)
3)reducer被第一次調用時,是store自動觸發(fā)的,傳遞的preState是undefined
2)demo
//redux文件夾下新建reducers文件夾
//新建count_reducer.js
import {INCREMENT, DECREMENT} from '../constant'
//監(jiān)測提交過來的action,preState是前一條數(shù)據(jù),初始化時默認為0
const counter = (preState = 0,action)=>{
const {type, data}= action
switch(type){
case INCREMENT:
return preState + data;
case DECREMENT:
return preState - data;
default:
return preState;
}
}
export default counter;
//redux文件夾下新建reducers文件夾
//新建user_reducer.js
import { SET_OPERATOR } from '../constant'
const operator = (preState = {}, action)=>{
const {type, data}= action
switch(type){
case SET_OPERATOR:
return Object.assign(preState, data);
default :
return preState
}
}
export default operator;
//redux文件夾下新建reducers文件夾
//新建index.js
import { combineReducers } from 'redux';
import counter from './count_reducer';
import operator from './user_reducer'
// 合并多個 reduce
const rootReducers = combineReducers({
counter:counter,
operator:operator
});
export default rootReducers;
Count.jsx
1)含義
操作組件,里面包含數(shù)據(jù)加減,和數(shù)據(jù)賦值兩個功能
2)demo
//引入Count的UI組件
// import CountUI from '../../components/Count'
//引入action
import {
incrementAction,
decrementAction,
incrementAsyncAction
} from '../../redux/actions/count_actions'
//引入connect用于連接UI組件與redux
import { connect } from 'react-redux'
// import store from '../../redux/store'
import React, { Component } from 'react'
import store from '../../redux/store'
import { setOperatorAction } from '../../redux/actions/user_action'
class Count extends Component {
state = {
}
//加
increment=()=>{
const {value}=this.selectNumber
this.props.increment(value*1)
}
//減
decrement=()=>{
const { value } = this.selectNumber
this.props.decrement(value*1)
}
//當前求和的數(shù)據(jù)為奇數(shù)再加
incrementIfOdd=()=>{
const counter = this.props.count.counter
const { value } = this.selectNumber
if(counter % 2 !=0) {
this.props.increment(value*1)
}
}
//異步加
incrementAsync=()=>{
const { value } = this.selectNumber
this.props.incrementAsync(value*1, 1000)
}
addUserInfo = () => {
const operator = {
name: '大黃'+Math.floor(Math.random()*100),
age: Math.floor(Math.random()*100)
}
this.props.setOperator(operator)
}
render() {
console.log(this.props)
return (
<div>
<h2>Person數(shù)組的長度{this.props.personLen.length}</h2>
<h1>當前求和為{this.props.count}</h1>
<select ref={c=>this.selectNumber =c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={()=>{this.increment()}}>+</button>
<button onClick={()=>{this.decrement()}}>-</button>
<button onClick={()=>{this.incrementIfOdd()}}>如果為奇數(shù)</button>
<button onClick={()=>{this.incrementAsync ()}}>異步增加 </button>
</div>
)
}
}
//a函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---狀態(tài)
const mapStateToProps = (state)=> ({count: state.counter, personLen: state.operator})
//b函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---操作狀態(tài)的方法
//一般寫法
// const mapDispatchToProps = (dispatch)=> ({
// increment: (number)=> dispatch(incrementAction(number)),
// decrement: (number)=> dispatch(decrementAction(number)),
// incrementAsync: (number)=> dispatch(incrementAsyncAction(number, 2000)),
// })
//高級寫法
//因為用了react-redux能夠自動dispatch
const mapDispatchToProps = {
increment: incrementAction,
decrement: decrementAction,
incrementAsync: incrementAsyncAction,
setOperator: setOperatorAction
}
//創(chuàng)建一個容器組件
const CountContainer = connect(mapStateToProps, mapDispatchToProps)(Count)
//暴露容器組件
export default CountContainer;
//export default connect()(CountUI)
//App.js
import Count from './container/Count'
import Person from './container/Person'
// import store from './redux/store'
function App() {
return (
<div className="App">
<Count/>
<hr/>
<Person/>
</div>
);
}
export default App;
1)明確兩個概念:
1)UI組件:不能使用redux的api,只負責頁面的呈現(xiàn)和交互等
2)容器組件:負責和redux通信,將結果交給UI組件
2)如何創(chuàng)建一個容器組件---react-redux的connect函數(shù)
connect(mapStateToProps, mapDispatchToProps)(UI組件)
-mapStateToProps:映射狀態(tài),返回值是一個對象
-mapDispatchToProps:映射操作狀態(tài)的方法,返回值是一個對象
3)備注:容器組件中的store是靠props穿進去的,而不是在容器組件中直接引入
Person.jsx
//引入Count的UI組件
// import CountUI from '../../components/Count'
//引入action
//引入connect用于連接UI組件與redux
import { connect } from 'react-redux'
// import store from '../../redux/store'
import React, { Component } from 'react'
import { setOperatorAction } from '../../redux/actions/user_action'
class Count extends Component {
state = {
}
addUserInfo = () => {
const name = this.nameNode.value
const age = this.ageNode.value
const personObj = {id: Math.floor(Math.random()*100), name, age}
this.props.setOperator(personObj)
this.nameNode.value = ''
this.ageNode.value = ''
console.log(name, age)
}
render() {
console.log(this.props.operator, this.props.count)
return (
<div>
<h2>Person組件,Count組件的總和為{this.props.count}</h2>
<div>
<input ref={c=> this.nameNode= c} type="text" placeholder="輸入名字"/>
<input ref={c=> this.ageNode= c} type="text" placeholder="輸入年齡"/>
<button onClick={()=>{this.addUserInfo()}}>添加用戶信息</button>
<ul>
{
this.props.operator.map(item=>{
return <li key={item.id}>{item.name}---{item.age}</li>
})
}
</ul>
</div>
</div>
)
}
}
//a函數(shù)的返回對象的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組props的value---狀態(tài)
const mapStateToProps = (state)=> ({operator: state.operator, count: state.counter})
//高級寫法
//因為用了react-redux能夠自動dispatch
const mapDispatchToProps = {
setOperator: setOperatorAction
}
//創(chuàng)建一個容器組件
const CountContainer = connect(mapStateToProps, mapDispatchToProps)(Count)
//暴露容器組件
export default CountContainer;
//export default connect()(CountUI)
1)定義一個Person組件,和Count組件通過redux共享數(shù)據(jù)
2)為Person組件編寫,reducer、action,配置constant常量
3)重點:Person的reducer和Count的Reducer要使用combineReducer進行合并,合并后的總狀態(tài)是一個對象
4)交給store的是總reducer,最后注意在組件中取出狀態(tài)的時候,記得取到位
//index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import store from './redux/store'
import App from './App';
import {Provider} from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
/*給容器組件傳遞store */
<Provider store={store}>
<App />
</Provider>
);
// 監(jiān)聽redux中狀態(tài)的變化,如果redux的狀態(tài)發(fā)生了變化,
//那么重新渲染App組件
//react-redux不用再監(jiān)測了
// store.subscribe(() => {
// root.render(
// <Provider store={store}>
// <App />
// </Provider>
// );
// })
三、redux開發(fā)者工具的使用
npm i redux-devtools-extension
store文件
//引入redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'
// const store = createStore(rootReducers, composeWithDevTools())
const store = createStore(rootReducers, composeWithDevTools(applyMiddleware(thunk)))
總結
1)容器組件和UI組件整合成一個文件
2)無需自己給容器組件傳遞store,給<App/>包裹 <Provider store={store}>即可
3)使用了react-redux無需自己檢測redux中狀態(tài)的變化,容器組件可以自動完成這個工作
4)mapDispatchToProps也可以簡寫成一個對象
5)一個組件要和redux打交道要經(jīng)過幾步?
1)定義好UI組件---不暴露
2)引入connect生成一個容器組件,并暴露,寫法如下:
connect(state=>(
{key:value},//映射狀態(tài)
),
{
key:action//映射操作狀態(tài)的方法
})
在UI組件中通過this.props.***讀取和操作狀態(tài)
原文鏈接:https://blog.csdn.net/chenacxz/article/details/127837231
- 上一篇:JVM中的垃圾回收
- 下一篇:flutter中使用流式布局示例詳解_Android
相關推薦
- 2022-07-11 UVM中UVM_ERROR到達一定數(shù)量后結束
- 2022-03-28 OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配_C 語言
- 2023-01-05 詳解C++中四種類型的轉換_C 語言
- 2022-07-07 淺談Qt實現(xiàn)HTTP的Get/Post請求_C 語言
- 2022-08-01 C#中把FastReport.Net報表控件的數(shù)據(jù)保存到數(shù)據(jù)庫_C#教程
- 2022-05-03 Python?PyQt5學習之自定義信號_python
- 2022-06-07 Python?Numpy庫的超詳細教程_python
- 2022-09-19 C++中的explicit關鍵字詳解_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支