React hooks app saga использует history.pu sh, а затем некорректно отображает компонент - PullRequest
0 голосов
/ 17 июня 2020

Спасибо, что посмотрели этот вопрос. Я использую машинописный текст, чтобы написать демонстрацию входа в систему с реактивными хуками. У меня есть некоторые вопросы. 1. Я использую history.push('/home') при успешном входе в систему. но страница отображает компонент Notification. 2. Это лучший способ сделать скачок маршрутизатора в саге о входе в систему? Другой способ - сделать это в компоненте входа в систему. В случае успеха. Использовать для этого хук useHistory. Я предпочитаю первый способ сделать это. Я бэкэнд-программист, недавно пришедший писать frontend. Поэтому я не знаю, что лучше всего.

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;

my 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 отправит рассылку, сага это будет смотреть. 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;

при успешном входе в систему. на странице некорректно отображается компонент.

enter image description here

  "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"
  },

1 Ответ

2 голосов
/ 17 июня 2020

@ xiaodonghuan. В последней версии пакета history "5.0.0" произошли критические изменения. На данный момент вы можете изменить его версию на стабильную версию, например "4.10.1", которая будет работать.

Используйте команду ниже для версии истории изменений

npm install history@4.10.1

Надеюсь, это сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...