1

私は疑問に思っていました...redux-observableでajaxの代わりにfetchまたはaws-amplify Auth.sigInを使用するにはどうすればよいですか?

以下の create-react-app ベースのコードを実行すると、次のエラーが発生します。

TypeError: __WEBPACK_IMPORTED_MODULE_2_rxjs__.a.from is not a function

エラー

私が現在拡張しているアプリは、次のパッケージと redux アプローチを使用しています。

パッケージ.json

...
    "redux": "^4.0.0-rc.1",
    "redux-observable": "^1.0.0-beta.1",
    "rxjs": "^6.2.0",
    "rxjs-compat": "^6.2.0",
    "styled-components": "^3.3.2"
...

types.js

export default {
  LOGIN_REQUEST: 'LOGIN_REQUEST',
  LOGIN_SUCCESS: 'LOGIN_SUCCESS',
  LOGIN_FAILURE: 'LOGIN_FAILURE',
};

アクション.js

import Types from './types';

export const loginRequest = (payload) => ({
  type: Types.LOGIN_REQUEST,
  payload,
});

export const loginSuccess = (payload) => ({
  type: Types.LOGIN_SUCCESS,
  payload,
});

export const loginFailure = (payload) => ({
  type: Types.LOGIN_FAILURE,
  payload,
});

epics.js

import { ajax } from 'rxjs/observable/dom/ajax';
import { ofType } from 'redux-observable';
import { Observable, from } from 'rxjs';
import { catchError, mergeMap, switchMap, map } from 'rxjs/operators';

import { Auth } from 'aws-amplify';

import Types from './types';

const loginSuccess = payload => ({
  type: Types.LOGIN_SUCCESS,
  payload,
});

const loginFailure = payload => ({
  type: Types.LOGIN_FAILURE,
  payload,
});

const api = {
  signIn: (username, password) => {
    const request = Auth.signIn(username, password)
      .then(user => user.json())
      .catch(err => err);

    return Observable.from(request);
  }
};

const loginRequest = (action$, state$) =>
    action$.pipe(
    ofType(Types.LOGIN_REQUEST),
    mergeMap(action => {
      console.log('===> Epic - action.payload', action.payload);
      // This returns our Observable wrapping the Promise.
      return api.signIn(action.payload.username, action.payload.password)
        .map(payload => ({ type: Types.LOGIN_SUCCESS, payload }))
        .catchError(payload => ({ type: Types.LOGIN_FAILURE, payload }))
    })
  );

export default loginRequest;

Signin.js

import React, { Component } from 'react';
import { bindActionCreators, compose } from 'redux';
import { connect } from 'react-redux';

import classNames from 'classnames';
import PropTypes from 'prop-types';

import { Auth } from 'aws-amplify';

import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import InputAdornment from '@material-ui/core/InputAdornment';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import Visibility from '@material-ui/icons/Visibility';
import VisibilityOff from '@material-ui/icons/VisibilityOff';

import { loginRequest } from './redux/actions';

const styles = theme => ({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  margin: {
    margin: theme.spacing.unit,
  },
  withoutLabel: {
    marginTop: theme.spacing.unit * 3,
  },
  textField: {
    flexBasis: 200,
  },
});

class SignIn extends Component {
  static propTypes = {
    auth: PropTypes.object,
    classes: PropTypes.object,
    data: PropTypes.array,
    isLoading: PropTypes.bool,
    loginRequest: PropTypes.func,
  }

  handleChange = prop => event => {
    this.setState({ [prop]: event.target.value });
  }

  handleMouseDownPassword = event => {
    event.preventDefault();
  }

  handleClickShowPassword = () => {
    this.setState({ showPassword: !this.state.showPassword });
  }

  handleSubmit = event => {
    event.preventDefault();

    console.log('handleSubmit - this.state', this.state);

    const payload = {
      username: this.state.username,
      pasword: this.state.password,
    }

    console.log('handleSubmit - payload', payload);

    this.props.loginRequest(payload);
  }

  state = {
    username: '',
    password: '',
    showPassword: false,
  }

  render() {
    const {
      auth,
      classes,
      data,
      isLoading,
    } = this.props

    return(
      <form
        noValidate
        autoComplete="off"
        onSubmit={(e) => { this.handleSubmit(e) } }
      >
        <TextField
          id="username"
          label="Username"
          onChange={this.handleChange('username')}
          value={this.state.username}
          margin="normal"
        />
        <FormControl className={classNames(classes.margin, classes.textField)}>
          <InputLabel htmlFor="password">Password</InputLabel>
          <Input
            id="password"
            type={this.state.showPassword ? 'text' : 'password'}
            value={this.state.password}
            onChange={this.handleChange('password')}
            endAdornment={
              <InputAdornment position="end">
                <IconButton
                  onClick={this.handleClickShowPassword}
                  onMouseDown={this.handleMouseDownPassword}
                >
                  {this.state.showPassword ? <VisibilityOff /> : <Visibility />}
                </IconButton>
              </InputAdornment>
            }
          />
        </FormControl>
        <Button
          variant="contained"
          color="primary"
          type="submit"
          label="Submit"
          className={classes.button}
        >
          Login
        </Button>
      </form>
    )
  }
}

const mapDispatchToProps = dispatch => (
  bindActionCreators({ loginRequest }, dispatch)
);

const mapStateToProps = state => ({
  auth: state.auth,
  data: state.user.data,
  isLoading: state.user.isLoading,
});

export default compose(withStyles(styles, { name: 'SignIn' }), connect(mapStateToProps, mapDispatchToProps))(SignIn);

役立つリソース:

ありがとう!

4

0 に答える 0