Redux狀態(tài)管理與React-router

Redux狀態(tài)管理

  • 概念:Redux是專注于狀態(tài)管理的庫
  • 組成:store,state,action,reducer
  • 安裝:yarn add redux
  • 補充:不僅僅是React,在Vue和Angular中也可以使用Redux
1,基本介紹
  • store:數據源,用于存儲狀態(tài)(state)
  • state:React中的狀態(tài),是只讀對象,不可直接修改
  • reducer:基本函數,用于對state的業(yè)務處理
  • action:普通對象,用于描述事件的行為,改變state
2,工作流
  • 用戶的一個行為(比如鼠標點擊)會觸發(fā)Action
  • Action會分發(fā)(dispatch)給Reducer
  • 在Reducer中會對狀態(tài)(stata)做相應的修改,并保存到數據源(STORE)中
  • 組件(Component)會監(jiān)聽數據源(STORE)中state的變化,從而改變頁面的展示內容
image.png
3,調試工具安裝(可選,建議安裝)
  • 添加Chrome擴展程序Redux Devtools
  • 安裝第三方庫redux-devtools-extension:yarn add redux-devtools-extension
4,在React中使用Redux(以切換菜單為例)
  • 安裝react-redux插件:yarn add react-redux
  • 創(chuàng)建Action模塊
// 文件:src/redux/action/index.js

// Action類型
export const type = {
    SWITCH_MENU:'SWITCH_MENU'
}

// Action函數
// 參數:用戶點擊的某個菜單名稱
// 返回值:對象,包括事件類型和用戶點擊的菜單名稱的對象
export function switchMenu(menuName){
    return{
        type:type.SWITCH_MENU,  // 事件類型
        menuName                // 菜單名稱
    }
}
  • 創(chuàng)建Reducer模塊
// 文件:src/redux/reducer/index.js

// 引入action類型
import { type } from './../action';

// 初始化state
const initialState = {
    menuName:'首頁',
}

// 業(yè)務處理函數
// 參數1:狀態(tài)(state),參數2:動作(action)
// 返回值:對象,是一個包括所有最新state的對象
export default (state = initialState, action) => {
    switch (action.type) {
        // 切換菜單
        case type.SWITCH_MENU:
            return {
                ...state,                 // 通過對象解構的方式保留原來的所有state
                menuName:action.menuName  // 更新menuName
            }
        default:
            return {
                ...state
            };
    }
} 
  • 創(chuàng)建Store模塊
    如果沒有安裝調試工具redux-devtools-extension,這樣寫。
// 文件:src/redux/store/index.js

// 引入reducer
import reducer from './../reducer';

// 引入createStore。這是Redux中的一個方法,用于創(chuàng)建一個數據源對象,保存數據
import { createStore } from 'redux';

// 導出數據源
export default () => createStore(reducer)

如果已經安裝調試工具redux-devtools-extension,這樣寫??梢杂肦edux Devtools清楚地看到redux狀態(tài)的變化(如果出錯了,就用上一種寫法,比較保險)

// 文件:src/redux/store/index.js

// 引入reducer
import reducer from './../reducer';

// 引入createStore。這是Redux中的一個方法,用于創(chuàng)建一個數據源對象,保存數據
import { createStore } from 'redux';

// 引入調試工具redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension';

// 導出數據源,可以方便地看到state變化
export default () => createStore(reducer,composeWithDevTools())
  • 添加Provider作為項目的根組件,用于數據的存儲
// 文件:index.js

import { Provider } from 'react-redux';      // 引入Provider組件,用于提供數據源
import configureStore from './redux/store';  // 導入數據源創(chuàng)建方法
const store = configureStore();              // 創(chuàng)建數據源

// 用Provider組件包裹根組件Router,以提供數據源
// 這樣Router里面的所有組件,都可以從數據源中獲取數據
ReactDOM.render(
    <Provider store={store}>
        <Router />
    </Provider>,
    document.getElementById('root'));
  • 通過connect方法將React組件和Redux連接起來
    更新redux的狀態(tài)
import { connect } from 'react-redux';              // 引入react-redux的connect方法
import { switchMenu } from './../../redux/action';  // 引入已經定義好的action

class Sidebar extends React.Component {
    // ...省略...
    currentTitleManage = () => {
        // ...省略...
        this.props.dispatch(switchMenu(currentTitle));  // 觸發(fā)switchMenu動作
        // ...省略...
    }
    // ...省略...
}

// 通過connect方法連接Sidebar組件和redux
export default connect()(Sidebar);

取得redux的狀態(tài)

import { connect } from 'react-redux';

class Header extends React.Component {
    // ...省略...
    {this.props.menuName}  // 取得菜單名稱
    // ...省略...
}

// 獲取數據源
const mapStateToProps = state => {
    return {
        menuName: state.menuName
    }
}

// 通過connect方法連接Header組件和redux
export default connect(mapStateToProps)(Header);

React-router

  • 安裝:yarn add react-router-dom
    為什么要安裝react-router-dom而不是react-router?
    因為在React Router 4.0中,react-router-dom是專門用于瀏覽器端的路由控制器,其中已經包含了基礎路由(react-router),所有我們只需要安裝react-router-dom就可以了。
1,react-router和react-router-dom理解
  • react-router:提供了一些router的核心api,包括Router,Route,Switch等
  • react-router-dom:提供了BrowserRouter,HashRouter,Route,Link,NavLink
2,react-router-dom核心用法
    // path:路徑,component:路徑對應的組件
    <Route path="/login" component={Login}/>

    // render:添加子路由
    // exact:精準匹配
    <Route path='/' render={()=>
        this.props.logout ? 
        (
            <Redirect to={`/login`}/>
        ) :
        (
            <Admin>
                <Switch>
                    <Route path="/home" component={Home}/>
                    <Route exact path='/contracts/list' component={ContractList}/>
                    ...
  • NavLink,Link
// NavLink:主要用于菜單導航

import { NavLink } from 'react-router-dom';

    // 第一種寫法:to地址
    <NavLink to='/home' replace>
        <span>首頁</span>
    </NavLink>

    // 第二種寫法:to對象,對象里包含一個pathname屬性
    <NavLink to={pathname:'/home'} replace>
        <span>首頁</span>
    </NavLink>

    // 第三種寫法:to對象,對象里包含比較多的屬性
    <NavLink to={pathname:'/home',search:'',hash:'',key:'123',state:{}} replace>
        <span>首頁</span>
    </NavLink>
// Link:主要用于鏈接
// 用法與NavLink一致
  • Switch
// 單個路由匹配:如果匹配到一個路由,就結束匹配
    <Switch>
        <Route path="/home" component={Home}/>
        <Route path='/contracts/list/add' component={ContractListDetail}/>
        <Route path='/contracts/list/edit/:id' component={ContractListDetail}/>
    </Switch>
  • Redirect
// 路由重定向

<Redirect to='/login'/>  // 重定向到login
  • 嵌套子路由
// "/home"是"/"下的子路由,需要用render的形式

<Route path='/' render={()=>
    <Admin>
        <Switch>
            <Route path="/home" component={Home}/>
        </Switch>
    </Admin>
}/>
// Admin組件

export default class Admin extends React.Component{
    render() {
        return (
            <Layout style={{ minHeight: '100vh' }}>
                <Sidebar/>
                <Layout>
                    <Header/>
                    <Content style={{ padding: '10px 10px 0'}}>
                        {this.props.children}  // 這里就是各個子路由對應的組件
                    </Content>
                    <Footer/>
                </Layout>
            </Layout>
        );
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容