无法使用Redux在已卸载的组件上执行React状态更新

时间:2019-04-30 06:51:30

标签: reactjs redux react-router redux-thunk

两个组件通过带Redux状态的条件渲染进行渲染,但是从一个组件更改Redux状态后,出现警告,提示无法对已卸载的组件执行状态更新。在LoginWrapper.js中,登录和重定向是使用Redux的isLoggedIn状态进行条件渲染的两个组件。

LoginWrapper.js

import React from 'react';
import Login from 'containers/Login';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { PropTypes } from 'prop-types';

const LoginWrapper = ({ isLoggedIn }) => {
  return (
    <div>
      {
        !isLoggedIn
        ?
        <Login />
        :
        <Redirect to="/profile" />
      }
    </div>
  )
}

LoginWrapper.defaultProps = {
  isLoggedIn: false
}

LoginWrapper.propTypes = {
  isLoggedIn: PropTypes.bool
}

const mapStateToProps = (state) => {
  return {
    isLoggedIn: state.auth.isLoggedIn
  }
}

export default connect(mapStateToProps)(LoginWrapper);

Login.js

import React from 'react';
import PropTypes from 'prop-types';
import { withRouter, Link } from 'react-router-dom';
import { withFormik, Form, Field } from 'formik';
import { connect } from 'react-redux';
import { logInUser } from 'actions/auth';
import { logInUrl } from "apis";
import ModalLayout from "shared/ModalLayout";
import * as Yup from 'yup';

const loginPost = (history, values, setSubmitting, setErrors, resetForm, logIn) => {
  const { username, password } = values;

  window.fetch(logInUrl, {
      method: 'POST',
      credentials: "same-origin",
      headers: {
        'Content-Type': "application/json"
      },
      body: JSON.stringify({
        "username": username,
        "password": password
      })
    })
    .then((results) => {
        return results.json();
    })
    .then((data) => {
      if(data.errors) {
        setErrors({ 'username': data.errors[0].msg });
      } else {
        logIn(data.user, history);
        resetForm();
      }
      setSubmitting(false);
    })
    .catch((err) => {
      console.log(err);
    })
}

const LogInForm = ({
    touched,
    errors,
    isSubmitting,
  }) => (
      <ModalLayout>
        <Form className="login-form">
          {touched.username && errors.username && <p className="login-error">{errors.username}</p>}
          <div className="login-username">
            <Field type="input" placeholder="Username" name="username" />
          </div>
          {touched.password && errors.password && <p className="login-error">{errors.password}</p>}
          <div className="login-password">
            <Field type="password" placeholder="Password" name="password" />
          </div>
          <div className="login-button">
            <button className="modal-button login-button" type="submit" disabled={isSubmitting}>
              Log in
            </button>
          </div>
          <div className="login-redirect">
            <Link to="/signup">Don&apos;t have an account.Create one</Link>
          </div>
        </Form>
      </ModalLayout>
    );

LogInForm.propTypes = {
  isSubmitting: PropTypes.bool.isRequired,
  errors: PropTypes.object.isRequired,
  touched: PropTypes.object.isRequired,
}

const FormikApp = withFormik({
  mapPropsToValues() {
    return {
      username: '',
      password: '',
    }
  },
  handleSubmit(values, { resetForm, setErrors, setSubmitting, props }) {
    const { logIn, history } = props;
    loginPost(history, values, setSubmitting, setErrors, resetForm, logIn);
  },
  validationSchema: Yup.object().shape({
    username: Yup.string().required('Username is required'),
    password: Yup.string().required('Password is required'),
  })
})(LogInForm);

export default withRouter(connect(null, { logIn: logInUser })(FormikApp));

动作

import {
  LOG_IN,
  LOG_OUT,
} from 'actions/types';

import { logInUrl } from 'apis';

export const logInUser = (user) => {
  return (dispatch) => {
    dispatch({
      type: LOG_IN,
      payload: user
    })
  }
}

export const logOutUser = () => {
  return {
    type: LOG_OUT
  }
}

减速器

import { LOG_IN, LOG_OUT } from 'actions/types';

const INITIAL_STATE = {
  isloggedIn: null,
  user: null,
  uid: null
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case LOG_IN:
      return { ...state, isLoggedIn: true, user: action.payload, uid: action.payload.id }
    case LOG_OUT:
      return { ...state, isLoggedIn: false, user: null, uid: null };
    default:
      return state;
  }
};

0 个答案:

没有答案
相关问题