React入門7-redux

1.背景介紹

react是單向數據流,一級一級組件傳遞這個過程是不能越級的,爲了解決深度嵌套, redux橫空出世

2. redux

安裝:npm/cnpm i redux  

(1).  分清兩個state

Redux中的state和React中的state完全不是一回事,React中的state是組件內部自己的狀態信息,而Redux中的state是Redux自己的數據

(2). Redux

redux工作流:

a.store

store:首先要創建一個對象store,這個對象有各種方法,用來讓外界獲取Redux的數據(store.getState),或者讓外界來修改Redux中的數據(store.dispatch)

b.action

action:描述我要幹啥,一般是一個對象的形式,其中有一個type字段是必須要有的,比如:{ type:‘撩妹’ },還可以帶點數據{ type:‘交朋友’,money: 100 }

c.reducer

reducer: 根據不同的action type處理邏輯

3. React-redux

安裝:npm/cnpm i react-redux 

在React-redux中有兩個比較關鍵的概念:Provider和connect方法。

a.Provider

一般我們都將頂層組件包裹在Provider組件之中,這樣的話,所有組件就都可以在react-redux的控制之下了,但是store必須作爲參數放到Provider組件中去。這個組件的目的是讓所有組件都能夠訪問到Redux中的數據。

b.connet

用法:connect(mapStateToProps, mapDispatchToProps)(MyComponent)

mapStateToProps 接收一個state,返回一個對象。 mapDispatchToProps 接收一個 dispatch 組成的對象。

4. demo使用

index.js: provider包含組件最外層,將store傳給最頂級組件

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

import {Provider} from 'react-redux';
import store from './store/index';

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

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

store/index.js: combineReducers合併所有模塊的reducer; createStore將ruduces轉化爲store

import {createStore, combineReducers} from 'redux'
import user from './user'
let reduces = combineReducers({
    user: user
})

export default createStore(reduces)

store/user.js: 抽象的reducer

import {SET_NAME, ADD_AGE} from '../actions'

function userReducer(state={ name: 'david', age: 18 }, action) {
    switch(action.type) {
        case SET_NAME: 
            return {
                ...state,
                name: action.name
            };
        case ADD_AGE: 
            return {
                ...state,
                age: state.age + action.age
            };
        default:
            return state;
    }
}

export default userReducer

actions.js: 定義type

export const SET_NAME = 'set_name'
export const ADD_AGE = 'add_age'

Home.js: 組件中使用connect, 可以得到redux的state,可以改變state的方法

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';

class Home extends Component {
    constructor(...args) {
        super(...args);
        this.state = {
            inputName: ''
        }
    }

    handelChangeName = (e) => {
        this.setState({
            inputName: e.target.value
        })
    }

    /**
     * @description 改變名稱
     */
    changeName = (e) => {
        this.props.setName(this.state.inputName)
    }
    
    /**
     * @description 改變年齡
     */
    changeAge = (e) => {
        this.props.addAge(3)
    }

    render() {
        return (
            <div>
                <div>name: {this.props.name}</div>
                <div>age: {this.props.age}</div>
                <input type="text" placeholder="請輸入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={this.changeName}></input>
                <button onClick={this.changeAge}>+3</button>
            </div>
        );
    }
}

export default connect((state, props) => {
    return state.user
}, {
    setName(name){
        return {
            type: SET_NAME,
            name
        };
    },
    addAge(age){
        return {
            type: ADD_AGE,
            age
        };
    }
})(Home)

或者使用dispatch({type: SET_NAME, name: this.state.inputName}) 也可以達到相同的目的。

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';

class Home extends Component {
    constructor(...args) {
        super(...args);
        this.state = {
            inputName: ''
        }
    }

    handelChangeName = (e) => {
        this.setState({
            inputName: e.target.value
        })
    }

    /**
     * @description 改變名稱
     */
    changeName = (e) => {
        // this.props.setName(this.state.inputName)
        this.props.dispatch({type: SET_NAME, name: this.state.inputName})
    }
    
    /**
     * @description 改變年齡
     */
    changeAge = (e) => {
        // this.props.addAge(3)
        this.props.dispatch({type: ADD_AGE, age: 3})
    }

    render() {
        return (
            <div>
                <div>name: {this.props.name}</div>
                <div>age: {this.props.age}</div>
                <input type="text" placeholder="請輸入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={this.changeName}></input>
                <button onClick={this.changeAge}>+3</button>
            </div>
        );
    }
}

// export default connect((state, props) => {
//     return state.user
// }, {
//     setName(name){
//         return {
//             type: SET_NAME,
//             name
//         };
//     },
//     addAge(age){
//         return {
//             type: ADD_AGE,
//             age
//         };
//     }
// })(Home)


export default connect((state) => {
    return state.user
})(Home)

最後推薦使用方式

import React, {Component} from 'react'
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';

class Home extends Component {
    constructor(...args){
        super(...args)
        this.state = {
            inputName: ''
        }
    }

    handelChangeName = (e) => {
        this.setState({
            inputName: e.target.value
        })
    }

    render() {
        return (
            <div> dashboard
                <div>name: {this.props.user.name}</div>
                <div>age: {this.props.user.age}</div>
                <input type="text" placeholder="請輸入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={() => this.props.changeName(this.state.inputName)}></input>
                <button onClick={this.props.changeAge}>+3</button>
            </div>
        );
    }
}

// 不用裝飾器設置 Redux
const mapStateToProps = (state) => {
    return { user: state.user }
}

const mapDispatchToProps = (dispatch, ownProps) => ({
    changeName: (name) => 
    {
        dispatch({type: SET_NAME, name: name})
    },
    changeAge: () => {
        dispatch({type: ADD_AGE, age: 3})
    }
})
  
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)

總結:

I. 單向數據流
state->component->action->state...

II.redux——集中狀態管理
provider:包在組件最外面
connect:狀態映射
reducer:狀態對象
action: 狀態更新

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章