连接-反应-路由器推送称为“无所事事”



有一个Login组件

// @flow
import type {
  TState as TAuth,
} from '../redux';
import * as React from 'react';
import Button from '@material-ui/core/Button';
import FormControl from '@material-ui/core/FormControl';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import Paper from '@material-ui/core/Paper';
import { withNamespaces } from 'react-i18next';
import { Link } from 'react-router-dom';
import {
  connect,
} from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import useStyles from './styles';
import { login } from '../../redux';
import { push } from 'connected-react-router';
const logo = './assets/images/logo.png';
const {
  useEffect,
} = React;
type TInputProps = {
  input: Object,
  meta: {
    submitting: boolean,
  }
}
const UserNameInput = (props: TInputProps) => (
  <Input
    id="userName"
    name="userName"
    autoComplete="userName"
    autoFocus
    {...props}
    {...props.input}
    disabled={props.meta.submitting}
  />
);
const PasswordInput = (props: TInputProps) => (
  <Input
    name="password"
    type="password"
    id="password"
    autoComplete="current-password"
    {...props}
    {...props.input}
    disabled={props.meta.submitting}
  />
);
type TProps = {
  t: Function,
  login: Function,
  handleSubmit: Function,
  error: string,
  submitting: boolean,
  auth: TAuth,
}
// TODO: fix flow error inside
const Login = ({
  t,
  login,
  handleSubmit,
  error,
  submitting,
  auth,
}: TProps) => {
  const classes = useStyles();
  useEffect(() => {
    if (auth) {
      console.log('push', push);
      push('/dashboard');
    }
  }, [auth]);
  return (
    <main className={classes.main}>
      <Paper className={classes.paper}>
        <img src={logo} alt="logo" className={classes.logo} />
        <form
          className={classes.form}
          onSubmit={handleSubmit((values) => {
            // return here is very important
            // login returns a promise
            // so redux-form knows if it is in submission or finished
            // also important to return because
            // when throwing submissionErrors
            // redux-form can handle it correctly
            return login(values);
          })}
        >
          <FormControl margin="normal" required fullWidth>
            <Field
              name="userName"
              type="text"
              component={UserNameInput}
              label={
                <InputLabel htmlFor="userName">{t('Username')}</InputLabel>
              }
            />
          </FormControl>
          <FormControl margin="normal" required fullWidth>
            <Field
              name="password"
              type="password"
              component={PasswordInput}
              label={
                <InputLabel htmlFor="password">{t('Password')}</InputLabel>
              }
            />
          </FormControl>
          <div className={classes.error}>{error}</div>
          <Button
            disabled={submitting}
            type="submit"
            fullWidth
            variant="outlined"
            color="primary"
            className={classes.submit}
          >
            {t('Sign in')}
          </Button>
          <Link className={classes.forgot} to="/forgot">
            {t('Forgot Password?')}
          </Link>
        </form>
      </Paper>
    </main>
  );
};
const mapStateToProps = ({ auth }) => ({ auth });
const mapDispatchToProps = {
  login,
};
export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(
  reduxForm({ form: 'login' })(withNamespaces()(Login))
);

useEffect钩中,使用来自connected-react-routerpush。钩子发射正常,但之后什么也没发生。

同样,push用于login操作。

// @flow
import type {
  TReducer,
  THandlers,
  TAction,
  TThunkAction,
} from 'shared/utils/reduxHelpers';
import type {
  TUser,
} from 'shared/models/User';
import createReducer from 'shared/utils/reduxHelpers';
import urls from 'constants/urls';
import axios, { type $AxiosXHR } from 'axios';
import { SubmissionError } from 'redux-form';
import { push } from 'connected-react-router';
export type TState = ?{
  token: string,
  result: $ReadOnly<TUser>,
};
export const ON_LOGIN = 'ON_LOGIN';
export const login: ({ userName: string, password: string }) => TThunkAction =
  ({ userName, password }) => async (dispatch, getState) => {
    const res: $AxiosXHR<{username: string, password: string}, TState> =
      await axios.post(`${urls.url}/signin`, { username: userName, password })
        .catch((err) => {
          throw new SubmissionError({ _error: err.response.data.message });
        });
    const data: TState = res.data;
    dispatch({
      type: ON_LOGIN,
      payload: data,
    });
    push('/dashboard');
  };
const handlers: THandlers<TState, TAction<TState>> = {
  [ON_LOGIN]: (state, action) => action.payload,
};
const initialState = null;
const reducer: TReducer<TState> = createReducer(initialState, handlers);
export default reducer;

在这里,一切都很成功,dispatch发生了,不再发生push

问题出在哪里?

不应该

dispatch(push('/dashboard'));吗?

在调用函数之前,您只需要确保不创建中间件并传入历史记录 api createRootReducer即可。

如果你尝试过早地使用routerMiddleware(history)创建中间件,历史将作为undefined传入。按照 README.md 进行操作,因为它解释了确切的执行顺序。

    // configureStore.js
...
import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'
...
export const history = createBrowserHistory()
export default function configureStore(preloadedState) {
  const store = createStore(
    createRootReducer(history), // <-- Initiates the History API
    preloadedState,
    compose(
      applyMiddleware(
        routerMiddleware(history), // <--- Now history can be passed to middleware
        // ... other middlewares ...
      ),
    ),
  )
  return store
}

相关内容

  • 没有找到相关文章

最新更新