Javascript 为什么axios在我的程序中被调用了两次
我正试图通过redux设置配置文件状态。但是由于某些原因,我的axios被调用了两次 my database profile.jsJavascript 为什么axios在我的程序中被调用了两次,javascript,reactjs,axios,Javascript,Reactjs,Axios,我正试图通过redux设置配置文件状态。但是由于某些原因,我的axios被调用了两次 my database profile.js const mongoose = require("mongoose"); const Schema = mongoose.Schema; // Create Schema const ProfileSchema = new Schema({ user: { type: Schema.Types.ObjectId, ref: "users"
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));
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通过profileActions从createPreference类发布数据时,我收到了两个axios post请求。它首先按照预期填充首选项,但是它立即进行另一个调用,并且首选项再次设置为null
关于如何解决这个问题,有什么建议吗?因为我无法访问您的所有代码(也无法调试),所以这里有一个更好的获取数据的方法。我已经将其结构与您所拥有的紧密结合,如果您遵循工作示例,您应该能够消除问题 我所做的:
onSubmit={this.onSubmit}
重命名为更标准的声明性this.handleSubmit
方法handleSubmit
类方法中调用this.setState()
以删除selectedOption
值,然后在setState回调中调用getCurrentProfile(value,history)
(用tempArray
替换值)
更改为
axios.get(…)
调用添加了return
(我还包括了async/await
版本的getCurrentProfile
,这可能更容易理解,也可以用axios.get
调用代替axios.post
调用)重定向
,而是将重定向放置在操作
创建者中,作为历史。推送('/')代码>(请求成功发送后,它将用户重定向回“/”——如果出错,则不重定向)
null
),如果它是一个字符串,那么它将保持一个字符串(非
)…等等。使用PropTypes时,
如果不保持1:1模式,应用程序将抛出错误。例如,您最初设置profile:null
,但随后将其设置为profile:[Object,Object,Object…]
。相反,它最初应该是:profile:[]
PropTypes
时,避免使用诸如object
或array
等不明确的类型,而是描述它们的结构setProfileLoading
。您只需更新数据,连接的React组件将更新以反映新的更改。在短时间内分别调度两个redux操作很可能会导致组件闪烁(可以将其视为在一秒钟内调用this.setState()
两次,这将导致组件闪烁)李>
工作示例:
SelectOption.js
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";
import Select from "react-select";
import { clearCurrentProfile, getCurrentProfile } from "../actions";
const options = [
{ value: "todos?userId=1", label: "Todos" },
{ value: "comments?postId=1", label: "Comments" },
{ value: "users?id=1", label: "Users" },
{ value: "albums?userId=1", label: "Albums" }
];
class SelectOption extends Component {
state = {
selectedOption: []
};
handleSubmit = e => {
e.preventDefault();
const { getCurrentProfile, history } = this.props;
const { value } = this.state.selectedOption;
this.setState({ selectedOption: [] }, () =>
getCurrentProfile(value, history)
);
};
handleChange = selectedOption => this.setState({ selectedOption });
render = () => (
<div className="container">
<form onSubmit={this.handleSubmit}>
<Select
value={this.state.selectedOption}
onChange={this.handleChange}
options={options}
/>
<div className="save-button">
<button type="submit" className="uk-button uk-button-primary">
Save Preferences
</button>
</div>
<div className="clear-button">
<button
type="button"
onClick={this.props.clearCurrentProfile}
className="uk-button uk-button-danger"
>
Reset Preferences
</button>
</div>
</form>
</div>
);
}
export default connect(
state => ({ profile: state.profile }),
{ clearCurrentProfile, getCurrentProfile }
)(withRouter(SelectOption));
SelectOption.propTypes = {
clearCurrentProfile: PropTypes.func.isRequired,
getCurrentProfile: PropTypes.func.isRequired,
profile: PropTypes.shape({
profile: PropTypes.arrayOf(PropTypes.object),
profiles: PropTypes.arrayOf(PropTypes.object),
loading: PropTypes.bool
}).isRequired
};
import axios from "axios";
import { GET_PROFILE, PROFILE_LOADING, CLEAR_CURRENT_PROFILE } from "../types";
//Get current profile
export const getCurrentProfile = (preference, history) => dispatch => {
// dispatch(setProfileLoading()); // not needed
return axios
.get(`https://jsonplaceholder.typicode.com/${preference}`)
.then(res => {
dispatch({
type: GET_PROFILE,
payload: res.data
});
// history.push("/") // <== once data has been saved, push back to "/"
})
.catch(err =>
dispatch({
type: GET_PROFILE,
payload: { err }
})
);
};
//Get current profile (async/await)
// export const getCurrentProfile = (preference, history) => async dispatch => {
// try {
// dispatch(setProfileLoading()); // not needed
// const res = await axios.get(
// `https://jsonplaceholder.typicode.com/${preference}`
// );
// dispatch({
// type: GET_PROFILE,
// payload: res.data
// });
// // history.push("/") // <== once data has been saved, push back to "/"
// } catch (e) {
// dispatch({
// type: GET_PROFILE,
// payload: { e }
// });
// }
// };
//Profile Loading
export const setProfileLoading = () => ({ type: PROFILE_LOADING });
//Clear Profile
export const clearCurrentProfile = () => ({ type: CLEAR_CURRENT_PROFILE });
import { combineReducers } from "redux";
import { CLEAR_CURRENT_PROFILE, GET_PROFILE, PROFILE_LOADING } from "../types";
const initialState = {
profile: [],
profiles: [],
loading: false
};
const profileReducer = (state = initialState, { type, payload }) => {
switch (type) {
case PROFILE_LOADING:
return {
...state,
loading: true
};
case GET_PROFILE:
return {
...state,
profile: payload,
loading: false
};
case CLEAR_CURRENT_PROFILE:
return {
...state,
profile: []
};
default:
return state;
}
};
export default combineReducers({
profile: profileReducer
});
因为您在
onSubmit
Methode中调用它,并且它是getCurrentProfile
function@evgenifotia我想有人会叫它一次。你能解释一下这两个电话在哪里吗?这样我就可以更正了。在export const getCurrentProfile=preference=>dispatch=>{
inmy Profile ActionsClass
中,您能在export const getCurrentProfile=preference=>dispatch=>
import axios from "axios";
import { GET_PROFILE, PROFILE_LOADING, CLEAR_CURRENT_PROFILE } from "../types";
//Get current profile
export const getCurrentProfile = (preference, history) => dispatch => {
// dispatch(setProfileLoading()); // not needed
return axios
.get(`https://jsonplaceholder.typicode.com/${preference}`)
.then(res => {
dispatch({
type: GET_PROFILE,
payload: res.data
});
// history.push("/") // <== once data has been saved, push back to "/"
})
.catch(err =>
dispatch({
type: GET_PROFILE,
payload: { err }
})
);
};
//Get current profile (async/await)
// export const getCurrentProfile = (preference, history) => async dispatch => {
// try {
// dispatch(setProfileLoading()); // not needed
// const res = await axios.get(
// `https://jsonplaceholder.typicode.com/${preference}`
// );
// dispatch({
// type: GET_PROFILE,
// payload: res.data
// });
// // history.push("/") // <== once data has been saved, push back to "/"
// } catch (e) {
// dispatch({
// type: GET_PROFILE,
// payload: { e }
// });
// }
// };
//Profile Loading
export const setProfileLoading = () => ({ type: PROFILE_LOADING });
//Clear Profile
export const clearCurrentProfile = () => ({ type: CLEAR_CURRENT_PROFILE });
import { combineReducers } from "redux";
import { CLEAR_CURRENT_PROFILE, GET_PROFILE, PROFILE_LOADING } from "../types";
const initialState = {
profile: [],
profiles: [],
loading: false
};
const profileReducer = (state = initialState, { type, payload }) => {
switch (type) {
case PROFILE_LOADING:
return {
...state,
loading: true
};
case GET_PROFILE:
return {
...state,
profile: payload,
loading: false
};
case CLEAR_CURRENT_PROFILE:
return {
...state,
profile: []
};
default:
return state;
}
};
export default combineReducers({
profile: profileReducer
});