Redux Saga, кажется, делает неизвестный вызов API? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть форма для входа (построена с помощью формы Ant Design ). Это все связано с Redux 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, который завершается неудачно, поскольку учетные данные не передаются. enter image description here

Здесь показан вызов API, возвращающийся с 200, но затем возвращается с 400, потому что он снова ищет username

Я подозреваю, что это форма, которая может быть виновата, и, хотя я не хочу переключаться на другую библиотеку форм, я чувствую, что мне, возможно, придется это сделать. У кого-нибудь есть мысли?

1 Ответ

1 голос
/ 12 апреля 2019

takeLatest в идеале должен быть снабжен строкой.В вашем случае передается функция, которая возвращает объект.

takeLatest не проверяет содержимое (то есть ключи и значения) объекта.Это то, что вы должны сделать самостоятельно.

Итак, независимо от того, какое действие отправлено, запускается сага входа в систему, которая вызывает API входа в систему, с неподходящей полезной нагрузкой и, следовательно, с ошибкой.

Таким образом, чтобы избежать ошибки, вы можете передать строку в takeLatest или другими словами инициировать сагу входа в систему только при отправке Actions.LoginRequest (действие типа Actions.LoginRequest).

yield takeLatest(Actions.LoginRequest, loginSaga)
...