React hooks app saga 使用 history.push 然后不能正确渲染组件

React hooks app saga use history.push then doesn't render component correctly

感谢您查看此问题。我用 typescript 写了一个 react hooks login demo.I 有一些问题。 1. 我在登录成功时使用history.push('/home')。但页面呈现 Notification 组件。 2. 在 login saga 中进行路由器跳转是更好的方法吗?其他方法是在登录 component.when success.use useHistory 挂钩中执行 it.I 更喜欢第一种方法。我是后端程序员新来写frontend.so不知道什么方法最好

services/history.ts

import { createBrowserHistory } from 'history';

const history = createBrowserHistory();

export default history;

我的路由器

import React, { Suspense } from 'react';
import { Route, Switch, Router } from 'react-router-dom';
import Loading from '@components/Loading';
import history from '@services/history';
import routes from './routes';

const renderRoutes = routes.map(({ path, exact, component, key }) => (
  <Route exact={exact || false} path={path} key={key} component={component} />
));

const Routers: React.FC = () => (
  <Router history={history}>
    <Suspense fallback={<Loading />}>
      <Switch>{renderRoutes}</Switch>
    </Suspense>
  </Router>
);

export default Routers;

// my routes
import { lazy } from 'react';

const routes = [
  {
    path: '/',
    key: 'login',
    exact: true,
    component: lazy(() => import('./../views/login')),
  },
  {
    path: '/home',
    key: 'home',
    component: lazy(() => import('./../views/home')),
  },
];

export default routes;

我的login.tsx

const Login: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
  const dispatch = useDispatch();

  const handleSubmit = (values: any) => {
    setLoading(true);
    const { username, password } = values;
    dispatch(loginRequest(username, password));
  };

  return (
    <div className="login-page">
      <Form name="login" className="login-form" onFinish={handleSubmit}>
        <p className="login-title"> Go React</p>
        <FormItem
          name="username"
          rules={[
            { required: true, message: 'Please input your Username!' },
            { min: 4, message: 'min length of username is 4' },
            { max: 12, message: 'max length of username is 12' },
          ]}
        >
          <Input
            prefix={<UserOutlined className="site-form-item-icon" />}
            placeholder="Username"
            size="large"
          />
        </FormItem>

        <FormItem
          name="password"
          rules={[
            { required: true, message: 'Please input your Password!' },
            { min: 4, message: 'min length of password is 4' },
            { max: 12, message: 'max length of password is 12' },
          ]}
        >
          <Input
            prefix={<LockOutlined className="site-form-item-icon" />}
            type="password"
            placeholder="Password"
            size="large"
          />
        </FormItem>

        <FormItem>
          <Button
            htmlType="submit"
            type="primary"
            className="login-button"
            size="large"
          >
            <Spin indicator={antIcon} spinning={loading} />
            {loading ? ' Logging in' : ' Login'}
          </Button>
        </FormItem>
      </Form>
    </div>
  );
};

export default Login;

handlesubmit 将发送一个 dispatch,saga 将关注这个。 saga.ts

import { fork, all, take, call, put, cancel } from 'redux-saga/effects';
import { message } from 'antd';
import fetchLogin from '@services/login';
import TokenStorage from '@utils/storage';
import ILoginResponseData from '@models/login';
import UserModel from '@models/user';
import history from '@services/history';
import {
  loginFailed,
  loginSuccess,
  LOGIN_REQUEST,
  LOGIN_SUCCESS,
  LOGIN_FAILED,
} from './action';

function* LoginRequestSaga(username: string, password: string) {
  try {
    const result: ILoginResponseData = yield call(
      fetchLogin,
      username,
      password
    );
    if (result.code === '1') {
      TokenStorage.storeToken(result.token);
      message.success(result.msg);
      history.push('/home');         <-------------I do history jump in here.
      const user = UserModel.getUser(result.token);
      yield put(loginSuccess(user));
    } else {
      message.error(result.msg);
      yield put(loginFailed());
    }
  } catch (err) {
    message.error(err);
    yield put(loginFailed());
  }
}

function* watchLogin() {
  while (true) {
    const { authData } = yield take(LOGIN_REQUEST);
    const task = yield fork(
      LoginRequestSaga,
      authData.username,
      authData.password
    );
    const action = yield take([LOGIN_SUCCESS, LOGIN_FAILED]);
    if (action.type === LOGIN_SUCCESS) {
      yield cancel(task);
    }
  }
}

export default function* rootSaga() {
  yield all([watchLogin()]);
}

我的主页组件

import React from 'react';
import { useSelector } from 'react-redux';
import { RootState } from '@store/reducer';

const Home: React.FC = () => {
  const user = useSelector((state: RootState) => state.user);
  return <div>Current User:{user.name}</div>;
};

export default Home;

登录成功时。该页面未正确显示组件。

  "dependencies": {
    "@ant-design/icons": "^4.1.0",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/history": "^4.7.6",
    "@types/jest": "^24.0.0",
    "@types/jwt-decode": "^2.2.1",
    "@types/node": "^12.0.0",
    "@types/react": "^16.9.0",
    "@types/react-dom": "^16.9.0",
    "@types/react-redux": "^7.1.9",
    "@types/react-router-dom": "^5.1.5",
    "@types/store": "^2.0.2",
    "antd": "^4.2.5",
    "axios": "^0.19.2",
    "history": "^5.0.0",
    "jwt-decode": "^2.2.0",
    "node-sass": "^4.14.1",
    "react": "^16.13.1",
    "react-app-rewire-alias": "^0.1.6",
    "react-app-rewired": "^2.1.6",
    "react-dom": "^16.13.1",
    "react-redux": "^7.2.0",
    "react-router": "^5.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.1",
    "redux": "^4.0.5",
    "redux-saga": "^1.1.3",
    "typescript": "~3.7.2"
  },

@xiaodonghuan。 history 包的最新版本“5.0.0”中有一些重大变化。现在,您可以将其版本更改为稳定版本,即可以使用的“4.10.1”。

使用以下命令更改历史版本

npm install history@4.10.1

希望它能奏效。