Why Is Axios Being Called Twice In My Program
I am trying to set profile state through redux. However for some reason my axios is being called twice my database profile.js const mongoose = require('mongoose'); const Schema = m
Solution 1:
Since I don't have access to your all of your code (and can't debug it), here's a better approach to fetching data. I've structured it closely to what you have and if you follow the working example, you should be able to eliminate the problem.
What I did:
- Renamed
onSubmit={this.onSubmit}to a more standard declarativethis.handleSubmitmethod - Called
this.setState()in thehandleSubmitclass method to removeselectedOptionvalue, then in the setState callback, calledgetCurrentProfile(value, history)(substitute thevaluewith yourtempArray) - Changed your
<input type="submit" ... />to a<button type="submit" ... /> - Added a
returnfor theaxios.get(...)call (I've also included anasync/awaitversion ofgetCurrentProfilewhich might be easier to understand -- also substitute theaxios.getcall for youraxios.postcall) - Removed
Redirectand instead placed a redirect inside theactioncreator ashistory.push('/');(once request has been successfully sent, it'll redirect the user back to "/" -- if error, no redirect) - Always keep your redux state as a 1:1. In other words, if it's an array, then it stays an array (not
null), if it's a string, it stays a string (notnumber)...etc. When usingPropTypes,your app will throw errors if you do not keep this 1:1 pattern. For example, you're initially settingprofile: null, but then you set it asprofile: [ Object, Object, Object ... ]. Instead, it should initially be:profile: []. - When using
PropTypes, avoid ambiguous types such asobjectorarrayand instead describe how they are structured. - Due to the nature of redux and how you're setting your component up, you don't need to dispatch
setProfileLoading. You can just update your data and the connected React component will update to reflect the new change. Dispatching two redux actions separately within a short period of time will most likely lead to component flashing (think of it as callingthis.setState()twice within a second of each other -- it'll cause your component to flash).
Working example: https://codesandbox.io/s/ovjq7k7516
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
};
actions/index.js
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 });
reducers/index.js
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
});
Post a Comment for "Why Is Axios Being Called Twice In My Program"