上一章讲了redux的中间件,为开发者处理redux提供了一定的帮助,但是总的看下来,简便了,但是没有非常简便,今天可以看下dva和rematch这两个重型的改动是不是能有什么大效果。
dva
dva是蚂蚁开发的一套方案,它有自己的脚手架和配套cli,可以很方便dva起来,但是,我拒绝,我选择改造,从上一章cra搭建的项目开始改造
dva最重要的概念就是model,我们看下目录结构
注册model的时候,需要挨个注册,也就是app.model(user),app.model(shop),非常麻烦,看后续的步骤吧
// model下的user.js
export default {
namespace: "user",
state: {
name: "dd",
age: "",
},
reducers: {
setName(state, action) {
return { ...state, ...action.payload };
},
},
effects: {
*changeName({ payload }, { put }) {
yield put({ type: "setName", payload });
},
},
};
// model下的index.js
// 这就是刚才说的,动态注册model,不需要每次都去引入
const allModel = require.context("./", false, /\.js$/);
export default allModel
.keys()
.filter((item) => item !== "./index.js")
.map((key) => allModel(key));
// 入口文件index.js
import dva from "dva";
import { createHashHistory } from "history";
import "./index.css";
import App from "./App";
import models from "@/models";
import reportWebVitals from "./reportWebVitals";
const app = dva({
history: createHashHistory(),
});
// 动态注册
models.forEach((item) => {
app.model(item.default);
});
// app.model(require('./models/app').default);
app.router(App);
app.start("#root");
reportWebVitals();
// router.js 也改回了原来的版本
export default [
{
path: "/user",
component: () => import("@/pages/user"),
exact: true,
},
];
// user/index.js
import React from "react";
import { connect } from "dva";
import "./index.scss";
const UserPage = ({ name, dispatch }) => {
return (
<div>
{name}
<div
onClick={() => {
dispatch({
type: "user/changeName",
payload: { name: "gg" },
});
}}
>
改名
</div>
</div>
);
};
const mapToState = ({ user }) => {
return {
...user,
};
};
export default connect(mapToState)(UserPage);
dva的配置完成了,但是但是,有时候也会觉得,这种hoc方式,connect方式很烦,还用不了useSelector,不优雅。
rematch
rematch是我用的比较多的工具了,可能也是因为这个关系,我觉得rematch更加简便,还能使用react-router的hooks,舒服。 下面开始改造,其实他就提取了dva的优势,然后更好的跟redux结合,应该更能被称为是一个工具。
// model/user.js
export default {
state: {
name: "dd",
age: "",
},
reducers: {
setName(state, action) {
return { ...state, ...action };
},
},
effects: (dispatch) => ({
changeName(params) {
dispatch.user.setName(params);
},
}),
};
// model/index.js
import { init } from "@rematch/core";
import user from "./user";
const store = init({
models: {
user,
},
});
export default store;
// 入口index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import store from "@/model";
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
// routrer.js
import { lazy } from "react";
export default [
{
path: "/t1",
component: lazy(() => import("@/pages/t1")),
exact: true,
},
{
path: "/t2",
component: lazy(() => import("@/pages/t2")),
exact: true,
},
];
// App.js
import React, { Suspense } from "react";
import { HashRouter, Route, Routes } from "react-router-dom";
import routers from "@/routers";
function App() {
return (
<HashRouter>
<Routes>
{routers.map((item, i) => {
return (
<Route
key={i}
path={item.path}
element={
<Suspense fallback={<div>路由懒加载...</div>}>
<item.element />
</Suspense>
}
/>
);
})}
</Routes>
</HashRouter>
);
}
export default App;
// router.js路由表
import { lazy } from "react";
export default [
{
path: "/user",
element: lazy(() => import("@/pages/user")),
exact: true,
}
];
// user/index.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import "./index.scss";
const UserPage = () => {
const { name } = useSelector(({ user }) => ({
name: user.name,
}));
// 当然这里也可以直接用dispatch到指定的type
const disSelect = ({ user }) => ({
changeName: user.changeName,
});
const dispatch = useDispatch();
const { changeName } = disSelect(dispatch);
return (
<div>
{name}
<div
onClick={() => {
changeName({ name: "gg" });
}}
>
改名
</div>
</div>
);
};
export default UserPage;
done 参考: dva官方文档