为什么在我的程序中两次调用axios

时间:2018-10-09 21:06:54

标签: javascript reactjs axios

我正在尝试通过Redux设置配置文件状态。但是由于某种原因,我的axios被叫了两次

我的数据库profile.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

// Create Schema
const ProfileSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: "users"
  },
  preference: [
    {
      type: String
    }
  ],

  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Profile = mongoose.model("profile", ProfileSchema);

myCreatePreferences类

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import checkboxes from "./checkboxes";
import Checkbox from "./Checkbox";
import axios from "axios";
import { Redirect } from "react-router";
import { withRouter } from "react-router-dom";
import Select from "react-select";
import { getCurrentProfile } from "../../actions/profileActions";
const options = [
  { value: "Guns", label: "Guns" },
  { value: "Gay Marriage", label: "Gay Marriage" },
  { value: "Abortion", label: "Abortion" },
  { value: "IT", label: "IT" }
];

class CreatePreferences extends Component {
  constructor() {
    super();
    this.state = {
      selectedOption: [],
      fireRedirect: false
    };
    this.onSubmit = this.onSubmit.bind(this);
  }
  onSubmit(e) {
    e.preventDefault();
    let tempArray = [];

    for (let i = 0; i < this.state.selectedOption.length; i++) {
      tempArray[i] = this.state.selectedOption[i].value;
    }
    const preference = {
      tempArray
    };
    //axios
    // .post("/api/profile/", { tempArray: tempArray })
    //.then(res => res.data)
    // .catch(err => console.log(err));
    this.props.getCurrentProfile(preference);
    this.setState({ fireRedirect: true });
  }

  handleChange = selectedOption => {
    this.setState({ selectedOption });
    console.log(`Option selected:`, selectedOption);
  };

  render() {
    const { selectedOption } = this.state;
    console.log(selectedOption.value);
    const { fireRedirect } = this.state;
    return (
      <div>
        <form onSubmit={this.onSubmit}>
          <Select
            value={selectedOption}
            isMulti
            onChange={this.handleChange}
            options={options}
          />
          <input
            type="submit"
            className="btn btn-info btn-block mt-4"
            value="Save Preferences"
          />
          {fireRedirect && <Redirect to={"/"} />}
        </form>
      </div>
    );
  }
}
CreatePreferences.propTypes = {
  profile: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
  profile: state.profile
});

export default connect(
  mapStateToProps,
  { getCurrentProfile }
)(withRouter(CreatePreferences));

我的profileActionsclass

import axios from "axios";

import {
  GET_PROFILE,
  PROFILE_LOADING,
  GET_ERRORS,
  CLEAR_CURRENT_PROFILE
} from "./types";

//Get current profile

export const getCurrentProfile = preference => dispatch => {
  dispatch(setProfileLoading());
  axios
    .post("/api/profile", preference)
    .then(res =>
      dispatch({
        type: GET_PROFILE,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: GET_PROFILE,
        payload: { err }
      })
    );
};

//Profile Loading

export const setProfileLoading = () => {
  return {
    type: PROFILE_LOADING
  };
};
//Clear Profile
export const clearCurrentProfile = () => {
  return {
    type: CLEAR_CURRENT_PROFILE
  };
};

profileReducer.js

import {
  GET_PROFILE,
  PROFILE_LOADING,
  CLEAR_CURRENT_PROFILE
} from "../actions/types";

const initialState = {
  profile: null,
  profiles: null,
  loading: false
};

export default function(state = initialState, action) {
  switch (action.type) {
    case PROFILE_LOADING:
      return {
        ...state,
        loading: true
      };
    case GET_PROFILE:
      return {
        ...state,
        profile: action.payload,
        loading: false
      };
    case CLEAR_CURRENT_PROFILE:
      return {
        ...state,
        profile: null
      };
    default:
      return state;
  }
}

index.js类的redux存储。

import { combineReducers } from "redux";
import authReducer from "./authReducer";
import errorReducer from "./errorReducer";
import profileReducer from "./profileReducer";
import postReducer from "./postReducer";
export default combineReducers({
  auth: authReducer,
  errors: errorReducer,
  profile: profileReducer,
  post: postReducer
});

当我通过axios通过profileAction从createPreference类发布数据时,我收到了两个axios发布请求。它首先会按预期的方式填充首选项,但是会立即进行另一个呼叫,并且该首选项再次设置为null。console.log(呼叫的)

preference: Array(2), _id: "5bbc73011f67820748fcd9ab", user: "5bb87db33cb39a844f0ea46a", date: "2018-10-09T09:21:05.968Z", __v: 0}
Dashboard.js:20 {preference: null, _id: "5bbc73011f67820748fcd9ab", user: "5bb87db33cb39a844f0ea46a", date: "2018-10-09T09:21:05.968Z", __v: 0}

关于如何解决此问题的任何建议?

1 个答案:

答案 0 :(得分:1)

由于我无权访问您的所有代码(并且无法调试),因此这是一种获取数据的更好方法。我已经根据您的实际情况对它进行了结构调整,如果您按照工作示例进行操作,则应该可以消除问题。

我做了什么:

  1. onSubmit={this.onSubmit}重命名为更标准的声明性this.handleSubmit方法
  2. this.setState()类方法中调用handleSubmit以删除selectedOption的值,然后在setState回调中调用getCurrentProfile(value, history)(用您的{替换value {1}})
  3. 将您的tempArray更改为<input type="submit" ... />
  4. <button type="submit" ... />调用添加了return(我还包括了axios.get(...)的{​​{1}}版本,可能更容易理解-也可以替换{{ 1}}拨打您的async/await电话)
  5. 删除了getCurrentProfile,而是将重定向放置在axios.get创建者内部,命名为axios.post(一旦请求发送成功,它将把用户重定向回“ /”-如果错误,没有重定向)
  6. 始终将Redux状态保持为1:1。换句话说,如果是数组,则保留为数组( Redirect);如果为字符串,则保留为字符串( {{ 1}})...等等。使用action时,如果不保持1:1模式,您的应用将抛出错误。例如,您最初设置为history.push('/');,但随后将其设置为null。相反,它最初应该是:number
  7. 使用PropTypes,时,请避免使用诸如profile: nullprofile: [ Object, Object, Object ... ]之类的模棱两可的类型,而应描述它们的结构。
  8. 由于redux的性质以及如何设置组件,因此不需要分派profile: []。您只需更新数据,连接的React组件就会更新以反映新的更改。在短时间内分别分派两个redux动作很可能会导致组件闪烁(将其视为彼此之间在一秒钟内两次调用PropTypes -会导致组件闪烁)。

工作示例:https://codesandbox.io/s/ovjq7k7516

SelectOption.js

object

actions / index.js

array

reducers / index.js

setProfileLoading