Redux Saga 似乎正在进行一个未知的 API 调用?

Redux Saga seems to be making an unknown API call?

我有一个登录表单(使用 Ant Design 的 Form 构建)。这一切都与 Redux Saga 相关联。在这个 Saga 中,我正在调用 API,一切似乎都正常,但神秘的是,当我使用 put 调度任何其他操作时,似乎有一个额外的神秘 API调用失败,因为它没有正确读取表单。

我的表格:

import React from 'react';
import { connect } from 'react-redux';
import { Form, Icon, Input, Button } from 'antd';
import { FormComponentProps } from 'antd/lib/form';

import { loginRequest, ICredentials } from '../redux/auth';
import { FormContainer, LoginContainer } from './styles';

type Props = {
  login: (data: ICredentials) => {};
}

class LoginForm extends React.Component<Props & FormComponentProps> {
  handleSubmit = (e: React.SyntheticEvent) => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.props.login(values)
      }
    });
  }

  render() {
    const { getFieldDecorator } = this.props.form;
    return (
      <FormContainer>
        <Form className="login-form">
          <Form.Item>
            {getFieldDecorator('username', {
              rules: [{ required: true, message: 'Please input your username!' }],
            })(
              <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
            )}
          </Form.Item>
          <Form.Item>
            {getFieldDecorator('password', {
              rules: [{ required: true, message: 'Please input your Password!' }],
            })(
              <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
            )}
          </Form.Item>
          <LoginContainer>
            <Button type="primary" htmlType="submit" className="login-form-button" onClick={this.handleSubmit}>
              Log in
            </Button>
          </LoginContainer>
        </Form>
      </FormContainer>
    );
  }
}

const mapDispatchToProps = { login: loginRequest };
const WrappedLoginForm = Form.create()(LoginForm);

export default connect(null, mapDispatchToProps)(WrappedLoginForm);

我的操作:

export const loginRequest = (data: ICredentials): Action => ({
  type: Actions.LoginRequest,
  payload: data,
});

我的减速器:

const initialState: State = {
  loading: false,
}

const reducer: Reducer<State> = (state = initialState, action: Actions & any) => {
  switch (action.type) {
    case Actions.LoginRequest:
      return {
        ...state,
        loading: true,
      }

    case Actions.LoginSuccess:
      return {
        ...state,
        loading: false,
      }

    default:
      return state;
  }
}

export default reducer;

我的传奇:

import { all, call, takeLatest, put } from 'redux-saga/effects';
import axios from 'axios';
import { push } from 'react-router-redux'
import message from 'antd/lib/message';
import { loginRequest, LoginRequest, loginSuccess } from './actions';
import { ICredentials } from './model';
import { AccessToken } from '../../storage/token';

const login = (payload: ICredentials) => axios({
  method: 'POST',
  url: //....
  data: {
    username: payload.username,
    password: payload.password,
    grant_type: 'password',
    scope: 'admin,super_admin',
  },
  headers: {
    'Content-Type': 'application/json',
    Authorization: //....
  }
});

function* loginSaga({ payload }: LoginRequest) {
  try {
    const data = yield call(login, payload);
    AccessToken.set({ ...data.data, retrieved_at: Date.now() / 1000 })
    yield call(message.success, 'Welcome!');
    // yield all([
    //   put(loginSuccess()),
    //   put(push('/'))
    // ]);
    // yield put(loginSuccess());
    // yield put(push('/'))
  } catch (err) {
    console.log(err)
  }
}

function* watcherSaga() {
  yield takeLatest(loginRequest, loginSaga)
}

export default watcherSaga;

在这个传奇中,当设置 AccessToken 时,我理想情况下想使用 react-router-redux 将用户推送到另一条路线。但是,似乎正在进行一个神秘的 API 调用,但由于没有传递凭据而失败。

图中显示的是 API 呼叫返回 200,但随后返回 400,因为它再次寻找 username

我怀疑可能是表单出了问题,虽然我不想切换到另一个表单库,但我觉得我可能不得不这样做。有人有什么想法吗?

takeLatest 理想情况下必须提供一个字符串。在您的情况下,传递了一个函数,其中 returns 一个对象。

takeLatest 不检查对象的内容(即键和值)。那是你必须自己做的事情。

因此,无论调度什么操作,都会启动登录 saga,它调用登录 api,负载不当,因此会出现错误。

因此,为避免错误,您可以将字符串传递给 takeLatest,或者换句话说,仅当 Actions.LoginRequestActions.LoginRequest 类型的操作)被调度时才启动登录 saga .

yield takeLatest(Actions.LoginRequest, loginSaga)