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不支持异步,而是为了将逻辑可以独立出来,而不是放在组件里去写异步函数,再dispatchaction到reducer。
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();