react之状态管理方式redux篇

413 阅读2分钟

redux, 被称为状态管理的容器,适用于任何框架,哪怕是原生js。不过操作起来,是有些麻烦的。 这里就主要记录和总结react 搭配 redux 的使用。

  • 为什么要用 redux

    使用redux顾名思义,是为了解决各个组件间共享状态的问题,react 官方其实提供了父子组件传值的方式,还有component composition,和context包裹的方式。所以需要根据复杂程度来选择合适的方式。

    一般redux的使用和context是矛盾的,选其一即可,如果业务逻辑比较简单,需要跨父子组件的共享状态不是很多,可以优先考虑使用context,相反,如果挺复杂的,那么还是直接redux搞起来。

  • redux, react-redux, redux-thunk, redux-toolkit的搭配及原因

    因为redux,并不是针对react开发设计的,所以需要安装react-redux将管理的状态和react组件渲联系起来。
    redux-thunk:这个主要是针对,异步的action,但是记住,并不是redux不支持异步,而是为了将逻辑可以独立出来,而不是放在组件里去写异步函数,再dispatch actionreducer
    redux-toolkit:这个工具,主要就是为了简化reducer的写法,不需要再switch去判断action里面的类型,然后执行各种逻辑。也不需要,去考虑返回一个深拷贝,全新的state,因为它里面已经做了处理。`

  • 示例代码

/src/store/index.ts

import { configureStore } from "@reduxjs/toolkit"
import { projectListSlice } from "screens/project-list/project-list.slice"
import { authSlice } from "store/auth.slice"

// 创建根Reducer, 也就是rootReducer
export const rootReducer = {
    projectList: ProjectListSlice.reducer
    auth: authSlice.reducer
    // 上面是通过redux-toolkit里,可以将不同的reducer写到不同的切片里。
}


// 创建根store 也就是rootStore
export const Store = configureStore({
    rootReducer
})

// 定义 dispatch的类型
export type AppDispatch = typeof store.dispatch

// 定义 rootState的类型
export type RootState = ReturnType<typeof store.getState>

/src/screens/project-list/project-list.slice

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { AppDispatch, RootState } from "store";
import { Project } from "screens/project-list/list";

// 定义state的类型
interface State {
    projectModalOpen: boolean
    projects: Project[]
}

// 初始化state
const initailState: State = {
    projectModalOpen: false,
    projects: []
}

export const ProjectListSlice = createSlice({
    name: 'ProjectListSlice',
    initailState,
    reducer: {
        openProjectModal(state) {
            state.projectModalOpen = true; 
        },
        closeProjectModal(state) {
            state.projectModalOpen = false;
        },
        setProjectList(state, action: PayloadAction<Project[]>) {
            state.projects = action.payload;
        },
    }
})

// 导出 projectSlice 的 action,提供给组件 dispatch 调用
export const ProjectListActions = ProjectListSlice.actions

// 导出每一个state,方便外面获取; 注意这里的state,是根state,
//所以返回需要点上projectList,这里的projectList是由store目录下的入口index.ts里定义的。
export const selectProjectModalOpen = (state: RootState) => state.projectList.projectModalOpen

调用action, 获取state

import { useDispatch } from "react-redux"
import { projectListActions } from "screens/project-list/project-list.slice";

export const ProjectList = () => {
    const dispatch = useDispatch()
    
    <div onClick={() => {dispatch(projectListActions.openProjectModal()} }></div>
}
  • 使用Provider包裹需要共享状态的组件

/context/index.ts

import React, { ReactNode } from "react";
import { AuthProvider } from "context/auth-context";
import { Provider } from "react-redux";
import { store } from "store";

export const AppProviders = ({ children }: { children: ReactNode }) => {
  return (
    <Provider store={store}>
       <AuthProvider>{children}</AuthProvider>
    </Provider>
  );
};



/index.ts

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { DevTools, loadServer } from "jira-dev-tool";
// 务必在jira-dev-tool后面引入
import "antd/dist/antd.less";
import { AppProviders } from "context";

loadServer(() =>
  ReactDOM.render(
    <React.StrictMode>
      <AppProviders>
        <DevTools />
        <App />
      </AppProviders>
    </React.StrictMode>,
    document.getElementById("root")
  )
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();