1. 程式人生 > >redux狀態管理和react-redux的結合使用

redux狀態管理和react-redux的結合使用

原文:  https://www.cnblogs.com/kelly2017/p/8034251.html

一:除錯

注意:Redux除錯工具。谷歌中搜redux同理react

新建store的時候判斷window.devToolsExtension
使用compose(組合函式)結合thunk外掛和window.devToolsExtens

二:Redux

Redux 是 JavaScript 狀態容器,專注於狀態管理的庫

整體來說是單一狀態。就是指的是單向的資料流

應用中所有的 state 都儲存在 store 中。 惟一改變 state 的辦法是dispatch觸發 action,為了描述 action 如何改變 state ,需要編寫 reducer。

redux中最重要的幾個:store     state     action    reducer

首先安裝redux   安裝:http://www.cnblogs.com/kelly2017/p/7930681.html

package.json中有

react-redux把狀態對映到子元件 分發reducer

redux  建立reducer action store等   

react-thunk  thunk處理髮送請求非同步。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

import { createStore } from 'redux';    

//新建一個store

//通過reducer來建立,是個形式為 (state, action) => state 的純函式。

//reducer描述了 action 如何把老的狀態state和action 生成新的狀態state

// action有type

function  couter(state=0, action) {

    switch (action.type){

        case '加'

            return state+1

        case '減'

            return state-1

        default:

        return 1

    }

}

const store=createStore( couter )

//1: 建立 Redux store 來存放應用的狀態(根據reducer來建立)

// store  應用中所有的 state 都儲存在一個單一的 store 中。

const init=store.getState()

//store.getState()隨時獲取最新的狀態

console.log(init)

//派發事件 

//需要狀態變更的時候 store.dispatch(action)來提交狀態變更

//改變內部 state 惟一方法是 dispatch 一個 action。

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

//console.log(store.getState())

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

//console.log(store.getState())

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

//console.log(store.getState)

function listener() {

    const current=store.getState()

    console.log(`現在的總數是${current}`)

}

store.subscribe(listener)

//subscribe 訂閱事件

//store.subscribe來監聽每次state修改

//每次dispatch都會執行listener

執行結果:

2:Redux和React

redux和react一起結合使用的方法:

1)
因為改變內部 state 惟一方法是 dispatch 一個 action。
所以把store.dispatch的方法傳遞給元件,使其內部可以呼叫修改狀態
react的修改狀態從之前的setState({})變成了由store來統一管理
2)
store.subscribe來監聽每次state修改
每次dispatch都會執行訂閱的事件
subscribe來定義render函式,每次修改都重新渲染頁面。
3)
react和redux的檔案分離

index.js中 建立store

訂閱subscribe只要狀態改變。就重新渲染頁面 render()

const store=createStore(couter)

新建store.以元件屬性的形式。新增到component元件裡

通過subscribe訂閱這個render函式,狀態有變化。render就會重新渲染頁面

1

2

3

4

5

6

7

8

9

10

11

12

13

import React from 'react';

import ReactDOM from 'react-dom';

import { createStore } from 'redux';

import App from './App';

import { couter,addFn,minusFn } from './index.redux';

import registerServiceWorker from './registerServiceWorker';

const  store=createStore(couter)

function render() {

    ReactDOM.render(<App store={store} addFn={addFn} minusFn={minusFn}/>, document.getElementById('root'));

}

render()

store.subscribe(render)

registerServiceWorker();

  

新建index.redux.js專門管理redux

存放reducer和 dispatch的action   //store.dispatch({type:'加'});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//通過reducer來建立。

const ADD="加";

const MINUS="減";

export function  couter(state=0, action) {

    switch (action.type){

        case ADD:

            return state+1

        case MINUS:

            return state-1

        default:

            return 1

    }

}

//store.dispatch({type:'加'});store.dispatch({type:'減'})

//action

export function addFn() {

    return { type:ADD }

}

export function minusFn() {

    return { type:MINUS }

}

 

app.js中使用

內部通過屬性獲取store以及相應的函式

1

<span style="font-size: 18px; font-family: 楷體">const store=this.props.store</span>

點選的時候要改變狀態 dispatch     //addFn() 執行返回的是物件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import React, { Component } from 'react';

class App extends Component {

    constructor(props){

        super(props)

    }

  render() {

   const store=this.props.store

   const addFn=this.props.addFn

   const minusFn=this.props.minusFn

   const init=store.getState()

    return (

      <div className="App">

          <h1>你好嗎?</h1>

          <p>現在的總數是:{init}</p>

          <button onClick={ ()=>store.dispatch( addFn() ) }>加1</button>

          <button onClick={ ()=>store.dispatch( minusFn() ) }>減1</button>

      </div>

    );

  }

}

export default App;

  

執行結果能實現簡單的通過redux管理狀態:

 

 三:redux非同步處理   redux-thunk

強制清除快取 。npm報錯。code為408(不允許安裝) 這時候執行  npm cache clean --force

處理非同步

redux預設情況下只處理同步,想要處理非同步,需要上面安裝的redux-thunk外掛
先引入:
import { createStore ,applyMiddleware } from 'redux';
import thunk from 'redux-thunk'
使用applyMiddleware在建立store的時候開啟中介軟體
const store=createStore(couter ,applyMiddleware(thunk))
之前action是個物件。直接dispatch這個物件就直接修改狀態。store.dispatch({type:MINUS})
export function minusFn() {
return { type:MINUS }
}
action可以返回函式,使用dispatch提交action
addAsyn() 這個函式可以返回個函式。
export function addAsyn() {
  return dispatch=>{
    setTimeout(()=>{
      dispatch(addFn())
     },2000)
}
dispatch是個引數。setTimeout結束之後手動執行dispatch

入口:index.js

app.js

index.redux.js

多向外暴露個函式

實現效果:

四:react和redux的結合使用     

外掛:react-redux

不適用subscribe釋出事件

提供provider和connect兩個介面連結react和redux

index.js調整

複製程式碼

 
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore ,applyMiddleware } from 'redux';
import thunk  from 'redux-thunk'
import { Provider } from 'react-redux'
import App from './App';
import { couter } from './index.redux';
import registerServiceWorker from './registerServiceWorker';
const  store=createStore(couter , applyMiddleware(thunk))
ReactDOM.render(
    (<Provider store={store}>
        < App />
    </Provider>)
    , document.getElementById('root'));
registerServiceWorker();
 

複製程式碼

 

 app.js中  

connect負責從外部獲取元件需要的引數。放到props中

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

import React, { Component } from 'react';

import { connect } from 'react-redux'

import {addFn,minusFn,addAsyn} from './index.redux'

class App extends Component {

  render() {

   const num=this.props.num

   const addFn=this.props.addFn

   const minusFn=this.props.minusFn

   const addAsyn=this.props.addAsyn

    return (

      <div className="App">

          <h1>你好嗎?</h1>

          <p> { num }</p>

          <button onClick={addFn}>加1</button>

          <button onClick={minusFn}>減1</button>

          <button onClick={addAsyn}>非同步加1</button>

      </div>

    );

  }

}

//num  state狀態 對映到屬性裡面

const mapStatetoProps=(state)=>{

   return {num:state}

}

//num 可以通過props獲取

const actionCreators={addFn,minusFn,addAsyn}

//addFn 自動有了dispatch的功能 onClick={addFn}

//addFn  minusFn  minusFn會被對映到props裡面

//this.props.addFn 可以通過props獲取

App=connect(mapStatetoProps,actionCreators)(App)

export default App;

 

  

 

 

五:@優化

安裝外掛,配置package.json介紹:http://www.cnblogs.com/kelly2017/p/7930681.html

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import { connect } from 'react-redux'

import {addFn,minusFn,addAsyn} from './index.redux'

//num  state狀態 對映到屬性裡面

// const mapStatetoProps=(state)=>{

//     return {num:state}

// }

//num 可以通過props獲取

// const actionCreators={addFn,minusFn,addAsyn}

//addFn 自動有了dispatch的功能 onClick={addFn}

//addFn  minusFn  minusFn會被對映到props裡面

//this.props.addFn 可以通過props獲取

//App=connect(mapStatetoProps,actionCreators)(App)

//@connect(mapStatetoProps,actionCreators)

@connect(

    (state)=>({num:state}),<br>    //第一個引數,state裡的屬性放到props裡面

    {addFn,minusFn,addAsyn}<br>    //方法放到props裡

)

  

 六:多個reducer之間的合併問題

新建一個專門用來合併用的reducer.js 主要的合併的方法 combineReducers

//多個reducer之間的合併  並且返回
import {combineReducers} from 'redux'
//redux提供的用於多個reducer合併的方法
// 裡面是個物件。羅列需要合併的reducer
import { couter } from './index.redux';  //專案中需要的reducer
import { auth } from './Auth.redux';   //專案中需要的reducer
export default combineReducers({couter,auth})

 在index.js中不需要之前引入的單個的reducer.直接引入合併之後的就可以

1

2

3

4

5

6

import reducer from './reducer'

import Dashboard from './Dashboard'

import registerServiceWorker from './registerServiceWorker';

//之前就一個couter reducer 現在加了一個auth reducer

const  store=createStore( reducer , applyMiddleware(thunk) )

console.log(store.getState())

  列印結果:合併之後的兩個reducer的初始狀態。