Redux簡(jiǎn)介

Redux 是一個(gè)獨(dú)立的 JavaScript 狀態(tài)管理庫企蹭,不依賴于任何其他庫

1. 安裝

npm i redux
yarn add redux

2. Redux核心概念

1)state:狀態(tài)
通常我們會(huì)把應(yīng)用中的數(shù)據(jù)存儲(chǔ)到一個(gè)對(duì)象樹(Object Tree) 中進(jìn)行統(tǒng)一管理白筹,我們把這個(gè)對(duì)象樹稱為:state

state 是只讀的,這里需要注意的是谅摄,為了保證數(shù)據(jù)狀態(tài)的可維護(hù)和測(cè)試徒河,不推薦直接修改 state 中的原數(shù)據(jù)

2)reducer:純函數(shù)
什么是純函數(shù)?

  • 相同的輸入永遠(yuǎn)返回相同的輸出
  • 不修改函數(shù)的輸入值
  • 不依賴外部環(huán)境狀態(tài)送漠,只依賴其參數(shù)
  • 無任何副作用

使用純函數(shù)的好處:

  • 便于測(cè)試
  • 有利重構(gòu)

3)store:倉庫
為了對(duì) state顽照,Reducer,action 進(jìn)行統(tǒng)一管理和維護(hù)闽寡,我們需要?jiǎng)?chuàng)建一個(gè) Store 對(duì)象

  • getState: ? getState() // 獲取 redux 存儲(chǔ)的狀態(tài)
  • dispatch: ? dispatch(action) // 發(fā)起一個(gè)修改
    調(diào)用 dispatch代兵,store 會(huì)調(diào)用其綁定的 reducer 函數(shù),并且會(huì)將當(dāng)前的 state 和 action 傳入 reducer爷狈。然后獲取到 reducer 的返回值植影,指定為倉庫的 state
  • replaceReducer: ? replaceReducer(nextReducer) // 替換掉當(dāng)前的 reducer
  • subscribe //監(jiān)聽狀態(tài)發(fā)生改變

4)action:動(dòng)作
action 是一個(gè)純對(duì)象(普通對(duì)象),action 必須有一個(gè) type 屬性涎永,用于描述我們對(duì) state 做出何種修改
我們對(duì) state 的修改是通過 reducer 純函數(shù)來進(jìn)行的思币,同時(shí)通過傳入的 action 來執(zhí)行具體的操作,action 是一個(gè)對(duì)象

  • type 屬性 : 表示要進(jìn)行操作的動(dòng)作類型土辩,增刪改查……
  • payload屬性 : 操作 state 的同時(shí)傳入的數(shù)據(jù)

但是這里需要注意的是支救,我們不直接去調(diào)用 Reducer 函數(shù),而是通過 Store 對(duì)象提供的 dispatch 方法來調(diào)用

3.redux三大原則

  • 單一數(shù)據(jù)源: 整個(gè)應(yīng)用的 state 被儲(chǔ)存在一棵 object tree 中拷淘,并且這個(gè) object tree 只存在于唯一一個(gè) store 中
  • state 是只讀的: 唯一改變 state 的方法就是觸發(fā) action各墨,action 是一個(gè)用于描述已發(fā)生事件的普通對(duì)象
  • 使用純函數(shù)來執(zhí)行修改

4.redux API

1)createStore(reducer, [preloadedState], enhancer);

  • reducer (Function): 接收兩個(gè)參數(shù),分別是當(dāng)前的 state 樹和要處理的 action启涯,返回新的 state 樹贬堵。
  • [preloadedState] (any): 初始時(shí)的 state。 在同構(gòu)應(yīng)用中结洼,你可以決定是否把服務(wù)端傳來的 state 后傳給它黎做,或者從之前保存的用戶會(huì)話中恢復(fù)一個(gè)傳給它。如果你使用 combineReducers 創(chuàng)建 - reducer松忍,它必須是一個(gè)普通對(duì)象蒸殿,與傳入的 keys 保持同樣的結(jié)構(gòu)。否則,你可以自由傳入任何 reducer 可理解的內(nèi)容宏所。
  • enhancer (Function): Store enhancer 是一個(gè)組合 store creator 的高階函數(shù)酥艳,返回一個(gè)新的強(qiáng)化過的 store creator。這與 middleware 相似爬骤,它也允許你通過復(fù)合函數(shù)改變 store 接口充石。
  • 返回值 (Store): 保存了應(yīng)用所有 state 的對(duì)象。改變 state 的惟一方法是 dispatch action霞玄。你也可以 subscribe 監(jiān)聽 state 的變化骤铃,然后更新 UI。
import { createStore } from "redux";

const store = createStore(reducer);

2)reducer

  • reducer(state,action)
function reducer(state = {
  count: 1
}, action) {
  //console.log(state,action);
  switch (action.type) {
    case "add":
      return {
        count: state.count + 1
      }
    case "minus":
      return {
        count: state.count - 1
      }
  }
  return state;
}

3)Store

  • getState()
  • dispatch(action)
  • subscribe(listener)
  • replaceReducer(nextReducer)
let unSubscribe = store.subscribe(() => {
  render();
});
render();
function render() {
  ReactDOM.render(<div>
    <p>{store.getState().count}</p>
    <button
      onClick={() => {
        store.dispatch({
          type: "add"
        })
      }}
    >+</button>
    <button
      onClick={() => {
        store.dispatch({
          type: "minus"
        })
      }}
    >-</button>
    <button onClick={unSubscribe}>取消監(jiān)聽</button>
    <button onClick={() => {
      unSubscribe = store.subscribe(() => {
        render();
      });
    }}>添加監(jiān)聽</button>
  </div>,
    document.querySelector("#root")
  );
}

4)combineReducers(reducers)
將 reducer 函數(shù)拆分成多個(gè)單獨(dú)的函數(shù)坷剧,拆分后的每個(gè)函數(shù)負(fù)責(zé)獨(dú)立管理 state 的一部分

import { createStore,combineReducers } from "redux";
import count from "./count";
import todo from "./todo";

const store = createStore(combineReducers({count,todo}));
export default store;

5)applyMiddleware(...middlewares) 中間件

中間件:更新的過程中惰爬,去做一些其他的事情

  • dispatch ---> reducer 更新state
  • dispatch --> 中間件 --> reducer

異步操作中間件:redux-thunk

  • 參數(shù)是對(duì)象,直接調(diào)用 reducer 修改我們的 state
  • 參數(shù)是函數(shù)听隐,調(diào)用該函數(shù)补鼻,并且把 dispatch 和 getState 傳遞我們的函數(shù)哄啄,可以在函數(shù)中雅任,進(jìn)行異步操作

store/store.js

import { createStore,combineReducers, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import count from "./count";
import todo from "./todo";
import topics from "./topics"
const store = createStore(combineReducers({count,todo,topics}),applyMiddleware(thunk));
export default store;

store/topics.js

import axios from "axios";

function topicsLoading(d,g) {
   const {type} = g().topics;
   return axios.get(`https://cnodejs.org/api/v1/topics?tab=${type}&page=1&limit=20`)
   .then(res=>{
     d({
       type: "topics/load",
       data:res.data.data
     })
   })
}

export {topicsLoading}

topics/topics.js

import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { topicsLoading } from "../store/topics";
import List from "./list";
import Nav from "./navs";

function Topics() {
  const {loading,type,data} = useSelector(state=>state.topics);
  const d = useDispatch();
  useEffect(()=>{
    d(topicsLoading);
  },[type]);
  return <div style={{
    textAlign:"center"
  }}>
    <Nav />
    {loading?<h3>數(shù)據(jù)請(qǐng)求中……</h3>:<List data={data} />}
    
  </div>
}

export default Topics;

5. react-redux

react項(xiàng)目中的 redux 綁定庫
1)安裝

npm i react-redux

2)<Provider store>

import ReactDOM from "react-dom";
import {Provider} from "react-redux";
import App from "./App";
import store from "./store/store";

ReactDOM.render(
  <Provider
    store={store}
  >
    <App />
  </Provider>,
  document.querySelector("#root")
);

3)connect()
在組件中獲取 react-redux 傳遞的 store 中的數(shù)據(jù)和操作

connect(mapStateToProps:()=>{})
mapStateToProps:根據(jù) store 中的 state,映射出 要傳遞給組件的 props
mapStateToProps 的返回值會(huì)傳遞給組件咨跌,mapStateToProps 的返回值必須是一個(gè)對(duì)象

import {connect} from "react-redux";

function Count(props) {
  //console.log(props);
  const {count,dispatch} = props;
  return <>
    <p>{count}</p>
    <button onClick={()=>{
      dispatch({
        type: "add"
      })
    }}>+</button>
    <button onClick={()=>{
      dispatch({
        type: "minus"
      })
    }}>-</button>
  </>
}

export default connect(state=>state)(Count);

4)hooks

  • useDispatch 獲取 dispatch
  • useStore 獲取 store
  • useSelector 獲取 state
import {useDispatch, useSelector, useStore} from "react-redux";

function Count() {
  const count = useSelector(state=>state.count);
  const d = useDispatch();
  console.log(useStore());
  return <>
    <p>{count}</p>
    <button onClick={()=>{
      d({
        type: "add"
      })
    }}>+</button>
    <button onClick={()=>{
      d({
        type: "minus"
      })
    }}>-</button>
  </>
}

export default Count;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沪么,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锌半,更是在濱河造成了極大的恐慌禽车,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刊殉,死亡現(xiàn)場(chǎng)離奇詭異殉摔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)记焊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門逸月,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遍膜,你說我怎么就攤上這事碗硬。” “怎么了瓢颅?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵恩尾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挽懦,道長(zhǎng)翰意,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮冀偶,結(jié)果婚禮上虎囚,老公的妹妹穿的比我還像新娘。我一直安慰自己蔫磨,他們只是感情好淘讥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著堤如,像睡著了一般蒲列。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搀罢,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天蝗岖,我揣著相機(jī)與錄音,去河邊找鬼榔至。 笑死抵赢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的唧取。 我是一名探鬼主播铅鲤,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼枫弟!你這毒婦竟也來了邢享?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤淡诗,失蹤者是張志新(化名)和其女友劉穎骇塘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體韩容,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡款违,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了群凶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片插爹。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖座掘,靈堂內(nèi)的尸體忽然破棺而出递惋,到底是詐尸還是另有隱情,我是刑警寧澤溢陪,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布萍虽,位于F島的核電站,受9級(jí)特大地震影響形真,放射性物質(zhì)發(fā)生泄漏杉编。R本人自食惡果不足惜超全,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一叔遂、第九天 我趴在偏房一處隱蔽的房頂上張望唾那。 院中可真熱鬧彰亥,春花似錦拒名、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽目养。三九已至救军,卻和暖如春财异,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唱遭。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國打工戳寸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拷泽。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓疫鹊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親司致。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拆吆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容