react狀態管理

狀態管理的實現

  1. 組件之外,可以在全局共享狀態/數據

    1. closure(閉包) 可以解決
  2. 有修改這個數據的明確方法,并且,能夠讓其他的方法感知到。

    1. 本質上,就是把監聽函數放在一個地方,必要時拿出來執行一下。
      1. 發布訂閱
      2. new Proxy / Object.defineProperty
  3. 修改狀態, 會觸發 UI 更新

    1. forceUpdate
    2. setState
    3. useState

手寫實現一個redux

index.jsx

import React, { useEffect, useState } from 'react';
import { createData } from './data';
const initState = {count : 1,age: 18,
}
const myReducer = (data,action)=>{switch(action.type){case "INCREMENT":return { ...data, count: data.count + 1 };case "DECREMENT":return { ...data, count: data.count - 1 };case "GROW_UP":return { ...data, age: data.age + 1 };default:return data;}
}
const dataObj  = createData(initState ,myReducer)
export default function GetData(){const [count, setCount] = useState(1)useEffect(() => {dataObject.subscribe(() => {let currentData = dataObject.getData();console.log('the subscribed data is: ', currentData);setCount(currentData.count);})}, [])const addClick = ()=>{createData.setDataByAction({type : "INCREMENT"})}const deleteClick= ()=>{createData.setDataByAction({type : "DECREMENT"})}return (<div><button onClick={addClick}>+</button><button onClick={deleteClick}>-</button></div>)
}

data.js

export const createData = function(init, reducer) {let data = init;let deps = [];function getData() {return data;};function subscribe(handler) {// 我們希望,訂閱了這個數據的 handler,在數據改變時,都能執行。deps.push(handler);}function UNSAFE_changeData(newData) {// 我們提供一個,修改這個 data 的方法data = newData;deps.forEach(fn => fn())}function setDataByAction(action) {data = reducer(data, action);deps.forEach(fn => fn())}// 既然 UNSAFE_changeData, 我們是不是要提供一個可預測的,可以固定能力去修改 data 的邏輯。// action, action 代表,我要如何修改這個數據。return {getData, subscribe, UNSAFE_changeData, setDataByAction}
};

手寫reducer合并

模擬定義redux的createStore 和 combineReducer 方法(redux.js)

export const createStore = function(reducer, initState) {let state = initState;let listeners = [];function getState() {return state;};function subscribe(handler) {// 我們希望,訂閱了這個數據的 handler,在數據改變時,都能執行。listeners.push(handler);};function dispatch(action) {// dispatch 一個 action, 通過你們注冊的 reducer,生成一個新的 state, 最后作用在界面上。// immutable, 我沒有改變 state 本身,而是生成了一個新的 state const currentState = reducer(state, action);state = currentState;listeners.forEach(fn => fn())};dispatch({ type: Symbol()});// 既然 UNSAFE_changeData, 我們是不是要提供一個可預測的,可以固定能力去修改 data 的邏輯。// action, action 代表,我要如何修改這個數據。return {getState, subscribe, dispatch}
};export const combineReducer = function(reducers) {const keys = Object.keys(reducers); // 先拿到[counter, info];return function(state = {}, action) {const nextState = {};keys.forEach((key) => {const reducer = reducers[key]; // counterRuducer, infoReducerconst prev = state[key]; // counter: {count: 0}, info: {age: 18}// 假設我是 ADD_COUNT 的 action, 那么循環執行完了以后,nextState 是不是分別為:// counter: {count: 1}, info: {age: 18}const next = reducer(prev, action); nextState[key] = next;});return nextState;}
}

調用:
配置storejs文件

import { combineReducer, createStore } from "./redux";
let initState = {counter: {count: 0},info: {name: 'xxx'}
}
function counterReducer(state, action){switch(action.type){//xxx省略代碼}
}
function infoReducer(state, action){switch(action.type){//xxx省略代碼}
}
const reducers = combineReducer({counter:counterReducer,info:infoReducer
})
const store = createStore(reducers,initState)
export default store

connect實現傳參

定義一個上下文context.js

import { createContext } from "react";
const _context = createContext({});
export default _context;

調用

import ReactContext from './context'
import store from './store'
<ReactContext.Provider value={store}><App/>
</ReactContext.Provider>

通過Provider ,可以使用Consumer 調用傳遞的store數據,并且通過connect可以直接調用store的方法和數據。connect原理其實通過配置高階組件,返回一個新的組件,將store和組件結合起來

connect兩個參數:mapStateToProps, mapDispatchToProps

import { useContext, useEffect, useState } from "react"
import ReduxContext from './context';export const connect = (mapStateToProps, mapDispatchToProps) => Component => {return function ConnectComponent(props) {const _store = useContext(ReduxContext);const [, setBool] = useState(true);const forceUpdate = () => setBool(val => !val);useEffect(() => {_store.subscribe(forceUpdate);}, [])return (<ReduxContext.Consumer>{store => <Component {...props}{...mapStateToProps(store.getState())}{...mapDispatchToProps(store.dispatch)}/>}</ReduxContext.Consumer>)}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13815.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13815.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13815.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java數據結構與算法(最小棧)

前言 設計一個支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常數時間內檢索到最小元素的棧。 實現 MinStack 類: MinStack() 初始化堆棧對象。void push(int val) 將元素val推入堆棧。void pop() 刪除堆棧頂部的元素。int top() 獲取堆棧頂部的元素。i…

Educational Codeforces Round 160 C. Game with Multiset (貪心之盡量選最大來填滿)

在這個問題中&#xff0c;最初會給你一個空的多集。您必須處理兩種類型的查詢&#xff1a; ADD x x x - 在多集合中添加一個等于 2 x 2x 2x 的元素&#xff1b; GET w w w - 詢問是否可以求當前多集的某個子集的和&#xff0c;并得到等于 w w w 的值。 輸入 第一行包含一…

java后端輪播圖的設計

對于表示輪播圖位置這種有限且較小范圍的數據&#xff0c;一般可以使用整數類型來表示。考慮到位置序號一般是非負整數且數量較少&#xff0c;可以選擇使用小范圍的整數類型&#xff0c;如下&#xff1a; 整數類型: 對于Java中&#xff0c;可以考慮使用 int 類型來表示位置序號…

Vue3 ts實現將assets中的圖片轉為file格式,實現本地圖片選擇上傳功能

Vue3 ts實現將assets中的圖片轉為file格式&#xff0c;實現本地圖片選擇上傳功能 1、需求描述2、關鍵代碼3、img標簽src使用變量打包后圖片無法展示 1、需求描述 用戶可以選項系統固定的幾個圖標&#xff0c;也可以自定義上傳圖片。系統固定圖標存在 src\assets\images\app 路徑…

sql注入——時間盲注

在sql注入的第九關中&#xff0c;我們既看不到返回值&#xff0c;也不能通過布爾盲注得到結果&#xff0c;這個時候還有一種方法就是通過頁面反應時間來獲取信息&#xff0c;就是時間盲注 第九關的代碼&#xff0c;可以看到無論是否正確&#xff0c;頁面都會返回You are in 可…

4---git命令詳解第一部分

一、提交文件方面命令&#xff1a; 1.1第一步&#xff1a;將需要提交的文件放進暫存區&#xff1a; 添加單個文件到暫存區stage&#xff1a; git add 文件名 添加多個文件到暫存區&#xff1a; git add 文件名1 文件名2 ... 將目錄下所有文件添加到暫存區&#xff1a; git…

【漏洞復現】用友U8 CRM uploadfile 文件上傳致RCE漏洞

0x01 產品簡介 用友U8 Cloud是用友推出的新一代云ERP&#xff0c;主要聚焦成長型、創新型企業&#xff0c;提供企業級云ERP整體解決方案。 0x02 漏洞概述 用友 U8 CRM客戶關系管理系統 uploadfle.php 文件存在任意文件上傳漏洞&#xff0c;未經身份驗證的攻擊者通過漏洞上傳…

Java基礎入門day52

day52 servlet 綜合案例 登錄功能 設置歡迎頁 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&q…

SpringBoot 國際化

如下四步 1 建資源文件 2 在yml文件中指定資源文件名稱 3 自定義類型轉換&#xff0c;轉換locale Configuration public class DefaultLocaleResolver implements LocaleResolver {Overridepublic Locale resolveLocale(HttpServletRequest request) {String locrequest.getP…

基于語音識別的智能電子病歷(三)之 M*Modal

討論“基于語音識別的智能電子病歷”&#xff0c;就繞不開 Nuance 和 M*Modal。這2個公司長時間的占據第一和第二的位置。下面介紹一下M*Modal。 這是2019年的一個新聞“專業醫療軟件提供商3M公司為自己購買了一份圣誕禮物&#xff0c;即M*Modal IP LLC的醫療技術業務&#xf…

SQL靶場搭建

概述 簡單介紹一下SQL靶場的搭建&#xff0c;以及在搭建過程中遇到的一些問題。使用該軟件搭建靶場相對簡單&#xff0c;適合新手小白。當然&#xff0c;也可以在自己的虛擬機下進行搭建&#xff0c;相對來說就較為復雜。本章主要講解使用Phpstudy進行SQL靶場搭建。 這里我推…

前后端編程語言和運行環境的理解

我已重新檢查了我的回答,并確保信息的準確性。以下是常用的編程語言,以及它們通常用于前端或后端開發,以及相應的框架和運行環境: 前端開發 JavaScript 框架:React, Angular, Vue.js, Ember.js, Backbone.js運行環境:Web 瀏覽器HTML (HyperText Markup Language) 不是編…

嵌入式學習——3——TCP-UDP 數據交互,握手,揮手

1、更新源 cd /etc/apt/ sudo cp sources.list sources.list.save 將原鏡像備份 sudo vim sources.list 將原鏡像修改成阿里源/清華源&#xff0c;如所述 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main …

Flutter 中的 DrawerController 小部件:全面指南

Flutter 中的 DrawerController 小部件&#xff1a;全面指南 Flutter 是一個流行的跨平臺移動應用開發框架&#xff0c;它提供了豐富的組件和工具來幫助開發者構建高質量的應用。在Flutter中&#xff0c;DrawerController并不是一個內置的組件&#xff0c;但是它的概念可以用于…

每周題解:牛的旅行

題目描述 牛的旅行 農民John的農場里有很多牧區。有的路徑連接一些特定的牧區。一片所有連通的牧區稱為一個牧場。但是就目前而言&#xff0c;你能看到至少有兩個牧區不連通。 現在&#xff0c;John想在農場里添加一條路徑 ( 注意&#xff0c;恰好一條 )。對這條路徑有這樣的…

RA-RISK ANALYSIS

文章目錄 一、期刊簡介二、征稿信息三、期刊表現四、投稿須知五、咨詢 一、期刊簡介 Risk Analysis代表風險分析學會出版&#xff0c;在ISI期刊引文報告中的社會科學、數學方法類別中排名前10位&#xff0c;為風險分析領域的新發展提供了焦點。這本國際同行評審期刊致力于發表…

MultiHop-RAG:多跳查詢的基準檢索增強生成

【摘要】檢索增強生成&#xff08;RAG&#xff09;通過檢索相關知識來增強大語言模型&#xff08;LLM&#xff09;&#xff0c;在減輕 LLM 幻覺和提高響應質量方面顯示出巨大的潛力&#xff0c;從而促進 LLM 在實踐中的廣泛采用。然而&#xff0c;我們發現現有的 RAG 系統不足以…

DNS域名解析服務器搭建

基礎介紹 DNS 從哪里獲取 IP 地址&#xff1f; 本地緩存&#xff1a; DNS服務器會將先前查詢過的域名和對應的IP地址存儲在本地緩存中&#xff0c;以便在后續查詢中加快響應速度。如果之前已經查詢過某個域名&#xff0c;DNS服務器會直接從本地緩存中獲取對應的IP地址。遞歸查…

02. Redis 事務

文章目錄 Redis 事務執行事務放棄事務編譯性異常運行時異常 Redis 事務 Redis 單條明令是原子性的&#xff0c;但Redis事務不保證原子性。 事務的本質就是&#xff1a;一組命令一起執行&#xff01;一個事務中的所有命令都會被序列化&#xff0c;在事務執行過程中&#xff0c;會…

2024-05-19 問AI: 大語言模型的BPE方向是什么意思?

文心一言 大語言模型的上下文中&#xff0c;BPE&#xff08;Byte-Pair Encoding&#xff09;是一種常用的子詞單元&#xff08;subword unit&#xff09;編碼方法&#xff0c;尤其在處理自然語言處理任務時。這種方法的主要目的是解決自然語言中的詞匯表大小問題&#xff0c;特…