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.handleSubmit
method - Called
this.setState()
in thehandleSubmit
class method to removeselectedOption
value, then in the setState callback, calledgetCurrentProfile(value, history)
(substitute thevalue
with yourtempArray
) - Changed your
<input type="submit" ... />
to a<button type="submit" ... />
- Added a
return
for theaxios.get(...)
call (I've also included anasync/await
version ofgetCurrentProfile
which might be easier to understand -- also substitute theaxios.get
call for youraxios.post
call) - Removed
Redirect
and instead placed a redirect inside theaction
creator 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 asobject
orarray
and 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"