dva和rematch

116 阅读2分钟

上一章讲了redux的中间件,为开发者处理redux提供了一定的帮助,但是总的看下来,简便了,但是没有非常简便,今天可以看下dva和rematch这两个重型的改动是不是能有什么大效果。 ​

dva

dva是蚂蚁开发的一套方案,它有自己的脚手架和配套cli,可以很方便dva起来,但是,我拒绝,我选择改造,从上一章cra搭建的项目开始改造 image.png

dva最重要的概念就是model,我们看下目录结构 image.png

注册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官方文档