您现在的位置是:首页 >技术杂谈 >如何react中使用redux和react-redux网站首页技术杂谈

如何react中使用redux和react-redux

前端布道人 2023-06-16 04:00:02
简介如何react中使用redux和react-redux

Redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。

可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。

不仅于此,它还提供 超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。

Redux 除了和 React 一起用外,还支持其它界面库。 它体小精悍(只有2kB,包括依赖)。

  • 英文原版:http://redux.js.org/
  • Redux 中文文档: https://cn.redux.js.org/
  • Redux 中文文档:https://www.redux.org.cn/

Redux Flow

三大原则

同步

官网地址:https://cn.redux.js.org/tutorials/essentials/part-1-overview-concepts

异步

官网地址:https://cn.redux.js.org/tutorials/essentials/part-5-async-logic

查看原图

react中使用redux

我们使用redux处理一个问题,点击按钮,实现左侧导航的展开与闭合,如下图:

查询文档,可知:点击按钮,修改Sider容器的collapsed属性为true,即可满足要求。

但是,由于头部部分按钮和改Sider容器不在一个组件,故此,就出现了兄弟组件的通信问题

安装组件

安装 reduxreact-redux

yarn add redux react-redux

创建redux文件夹及其他文件

创建的目录如下:

创建store

在redux文件夹下面,新建store.js用于创建store

import { createStore } from 'redux'
import { SidebarCollapsedReducers } from "./reducers/SidebarCollapsedReducers"; 

let store = createStore(SidebarCollapsedReducers)

我们在项目中,不可能只有一个Reducer。

随着应用变得越来越复杂,可以考虑将 reducer 函数 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分。

所以,我们还会用到一个api-- combineReducers

combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法。

合并后的 reducer 可以调用各个子 reducer,并把它们返回的结果合并成一个 state 对象。

由 combineReducers() 返回的 state 对象,会将传入的每个 reducer 返回的 state 按其传递给 combineReducers() 时对应的 key 进行命名。

示例

rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
// 这将返回如下的 state 对象
{
  potato: {
    // ... potatoes, 和一些其他由 potatoReducer 管理的 state 对象 ...
  },
  tomato: {
    // ... tomatoes, 和一些其他由 tomatoReducer 管理的 state 对象,比如说 sauce 属性 ...
  }
}

combineReducers

const reducer = combineReducers({
  SidebarCollapsedReducers,
});

改进store

import { createStore, combineReducers } from "redux";
import { SidebarCollapsedReducers } from "./reducers/SidebarCollapsedReducers"; // 导入 SidebarCollapsedReducers

const reducer = combineReducers({
  SidebarCollapsedReducers,
});
const store = createStore(reducer);

export default store; 

改进根组件

原先app.js

import IndexRouter from './router/IndexRouter' 
import './App.css' 
function App(){
  return <IndexRouter></IndexRouter>
  
}
export default App

引入 react-redux

改进app.js

import IndexRouter from './router/IndexRouter'
import {Provider} from 'react-redux'
import './App.css'
import store from './redux/store'
function App(){
  return <Provider store={store}> 
    <IndexRouter></IndexRouter>
  </Provider>
}
export default App

组件中使用

此功能涉及到两个组件:

  • TopHeader.js – 点击按钮部分 ,发布者
  • SideMenu.js – 订阅者

如下图

改造 TopHeader.js组件

// TopHeader.js

export default function TopHeader({ pageTitle }) {
// 其他代码
};

引入 react-redux,改进TopHeader.js

补充:connect()

react-redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。

connect(
  mapStateToProps
  mapDispatchToProps   
)(被包装的组件)
  • mapStateToProps

将state映射到 UI 组件的参数(props)。 const mapStateToProps =state=> state;

  • mapDispatchToProps

将用户对 UI 组件的操作映射成 Action。

const  mapDispatchToProps = (dispatch)=>{    
  return {        
    'Increment':()=> dispatch(IncrementAction({})),        
    'Decrement':() => dispatch(DecrementAction({})),    
  }
}

改进TopHeader.js

import {connect} from 'react-redux'

function TopHeader({ pageTitle }) {

  const changeCollapsed = ()=>{
    // 改变state的状态 
    props.changeCollapsed() 
  }
       
  // 其他代码

  return <button  onClick={()=>changeCollapsed()}>操作</button>
};

const mapStateToProps = (state, ownProps) => { 
  return {
    isCollapsed: state.SidebarCollapsedReducers.isCollapsed
  }
}

const mapDispatchToProps = {
  changeCollapsed(){
    return {
      type: 'change_collapsed', 
    }
  }
}  

export default connect(mapStateToProps,mapDispatchToProps)(TopHeader);

同理,修改SideMenu.js

import {connect} from 'react-redux'

function SideBar(props) { 
  // 其他代码

  return <Sider collapsed={props.isCollapsed}></Sider> // 注意这里
};

const mapStateToProps = (state, ownProps) => { 
  return {
    isCollapsed: state.SidebarCollapsedReducers.isCollapsed
  }
}
 
export default connect(mapStateToProps)(SideBar);

总结 – 全部代码

edux educersSidebarCollapsedReducers.js

export const SidebarCollapsedReducers = (prevState = {
    isCollapsed: false
}, action) => { 
    switch (action.type) {
        case 'change_collapsed':
            let newState = {...prevState} // 注意这里
            newState.isCollapsed = !newState.isCollapsed
            return newState
        default:
            return prevState
    } 
};

eduxstore.js

import { createStore, combineReducers } from "redux";
import { SidebarCollapsedReducers } from "./reducers/SidebarCollapsedReducers"; // 导入 SidebarCollapsedReducers

const reducer = combineReducers({
  SidebarCollapsedReducers,
});
const store = createStore(reducer);

export default store;

app.js

import IndexRouter from './router/IndexRouter'
import {Provider} from 'react-redux'
import './App.css'
import store from './redux/store'
function App(){
  return <Provider store={store}> 
    <IndexRouter></IndexRouter>
  </Provider>
}
export default App

组件

componentssandboxTopHeader.js

import React, { useEffect, useState } from "react";
import { Layout} from "antd"; 
import { connect } from "react-redux";
 
const { Header } = Layout;

function TopHeader(props) {   
  const changeCollapsed = ()=>{
    // 改变state的状态
    // dispatch
    console.log(props)
    props.changeCollapsed() 
  }

  return (
    <Header>
      <div style={{ display: "flex" }}>
        {React.createElement(
          props.isCollapsed ? MenuUnfoldOutlined : MenuFoldOutlined,
          {
            className: styles.trigger,
             onClick: () => changeCollapsed()
          }
        )} 
      </div> 
    </Header>
  );
}

const mapStateToProps = (state, ownProps) => { 
  return {
    isCollapsed: state.SidebarCollapsedReducers.isCollapsed
  }
}

const mapDispatchToProps = {
  changeCollapsed(){
    return {
      type: 'change_collapsed', 
    }
  }
}  
export default connect(mapStateToProps,mapDispatchToProps)(TopHeader);

componentssandboxSideMenu.js

import { useEffect, useState } from "react";
import { Layout, Menu } from "antd"; 
import { connect } from "react-redux";

const { Sider } = Layout;

function AppLayout(props) {  
  return ( 
      <Sider trigger={null} collapsible collapsed={props.isCollapsed}> // 注意这里 props.isCollapsed
        <div className={styles.logo}> {siteBaseConfig.siteName} </div>
        ... 
      </Sider> 
  );
}

const mapStateToProps = (state, ownProps) => { 
  return {
    isCollapsed: state.SidebarCollapsedReducers.isCollapsed
  }
} 

export default connect(mapStateToProps)(AppLayout);

参考文档

  • https://cn.redux.js.org/api/combinereducers
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。