try set header, in Ajax Request using axios
import React, { Component, PropTypes } from 'react'
import { Link, browserHistory } from 'react-router'
import { connect } from 'react-redux'
import axios from 'axios'
class Income extends Component {
constructor(props) {
super(props)
this.state = {
};
}
componentDidMount() {
axios.post('http://139.196.141.166:8084/course/income/outline', {
headers: { 'X-Authenticated-Userid': '15000500000#1' }
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div>
dsdss
</div>
)
}
But server returns me, that I not setup header. I setup it like in documentation, but header is not set.
There screen with error
From what I can see, the method call looks like this (from docs):
axios#post(url[, data[, config]])
As you are posting your config object as second argument, its interpreted as data, not as config (headers is part of the config object)
Edit: Here is an example:
axios.request({
url: 'http://139.196.141.166:8084/course/income/outline',
method: 'post',
headers: { 'X-Authenticated-Userid': '15000500000#1' }
})
Note that i switched over from .post() to .request() which only takes a config object. If you still want to use the .post() call, try:
axios.post(url, {}, { headers: ... })
Related
I am using react and I created a auth file to store all of my api request related to authentication purposes. I have inside a default function signin with a signin request, and I also want to store a signup request in the same file. I believe I am doing something wrong as it is not rendering properly.
here is my code:
import React from 'react'
import axios from 'axios';
export const signin = async(data)=>{
const config = {
headers: {
'Content-Type': 'application/json'
},
};
const response = await axios.post('http://localhost:5000/api/auth/signin', data, config);
return response;
};
const signup = async(data)=>{
const config = {
headers: {
'Content-Type': 'application/json'
},
};
const rep = await axios.post('http://localhost:5000/api/auth/signup', data, config);
return rep;
};
export default signin;
Like #saeed stated in his comment, you could export both signin and signup normally and import them somewhere else using import {signin, signup} from 'access'.
import React from 'react';
import axios from 'axios';
export const signin = async (data) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const response = await axios.post(
'http://localhost:5000/api/auth/signin',
data,
config,
);
return response;
};
export const signup = async (data) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const rep = await axios.post(
'http://localhost:5000/api/auth/signup',
data,
config,
);
return rep;
};
And to import the functions:
import {signin, signup} from 'somefile'
Until now, I had been importing axios in each Vue component where I wanted to make HTTP requests, like this.
<script lang="ts">
import axios from 'axios';
#Component
export default class ExamplePage extends Vue {
created(): void {
axios.post(some_path);
}
}
However, now I want to define a global interceptor for all axios requests, basically to catch all 401 unauthorized responses from the backend server (Rails) and log out the user.
My understanding so far is that you must instantiate axios once and use it everywhere, instead of importing and using a different instance in each file.
I've referred to this and this, and tried the below.
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
document.addEventListener('DOMContentLoaded', () => {
new Vue({
el: '#application',
router,
render: (h) => h(App),
});
});
axios.interceptors.response.use(
response => response,
error => {
const status = error.response;
if(status === 401) {
// do stuff
}
}
);
Vue.prototype.$http = axios
When I tried to call this.$http.put(...) in another file, it said property $http doesn't exist (I'm guessing it's because this in the context of that component is the component itself, but I'm not sure). How can I fix this?
[UPDATE] Thanks to the responses, I decided to initialize an axios instance in a separate file and then use that instead. However, this is still not working. The 401 responses don't seem to be triggering the interceptor at all.
Is there some additional configuration necessary?
// axios-instance.ts
import axios, { AxiosInstance } from 'axios';
const axiosInstance: AxiosInstance = axios.create();
axiosInstance.interceptors.response.use(
response => response.data,
async function(error) {
console.log("THIS IS THE 401 INTERCEPTOR")
const status = error.response;
if(status === 401) {
// Log out user
}
}
);
export default axiosInstance;
// Some component
<script lang="ts">
import axiosInstance from 'axios-instance';
#Component
export default class ExamplePage extends Vue {
created(): void {
axiosInstance.post(some_path);
}
}
Doesn't solve your question directly, but the way I create instance of axios is:
// axios-instance.js
import axios from 'axios'
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance
After you just import the instance
// application.js
import axios from '../../axios-instance'
You can't use this when you aren't in the vue instance.
Try this:
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
axios.interceptors.response.use(
response => response,
error => {
const status = error.response;
if(status === 401) {
// do stuff
}
}
}
);
Vue.prototype.$http = axios;
const VueInstance = new Vue({
el: '#application',
router,
render: (h) => h(App),
});
Now you can make HTTP request using this.$http:
<script>
export default {
methods: {
doStuff() {
this.$http.post('path_to_post_request').then(({ data }) => {
// do something with received data
}).catch((e) => {});
}
}
}
</script>
I had the same problem.
It is not so clear in Axios API docs that error responses should be intercepted in the response interceptor's error callback.
It should be done like this:
axios.interceptors.response.use(function (response) {
//This is the success callback in case u ever need it
return response;
}, function (error) {
// This is the callback I was talking about.
// Do something with request error
// Tip: error.response is the actual response with error code
return Promise.reject(error);
})
This can be seen in the Axios API Documentation - Interceptors section
I recommend that you implement the axios instance in a separate js file:
// utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: '',
headers: {},
withCredentials: true,
// ...other options
})
// request interceptor
service.interceptors.request.use(config => {
// ...
return config
}, err => {
return Promise.reject(err)
})
// response interceptor
service.interceptors.response.use(response => {
// ...
return response
}, err => {
return Promise.reject(err)
})
export default service
And then you can using http request like this:
import request from '#/utils/request'
request({
url: '',
method: 'post',
data: {}
}).then(res => {
// Do something after the request is successful
}).catch(err => {
// Do something after the request fails
})
Try implementing a service:
src / services / yourservice.js
import axios from 'axios'
const apiClient = axios.create({
baseURL: 'https://example.com/api',
withCredentials: false,
timeout: 1000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa('api_username_here' + ':' + 'api_password_here')
}
})
export default {
getOrders(){
return apiClient.get('/orders?status=processing')
},
getProducts(id){
return apiClient.get('/products/' + id)
},
}
Use the service in a Component:
src / component / yourcomponent.vue
import YourService from '#/services/YourService.js';
data() {
return {
orders: null, //Typescript
}
},
created() {
yourservice.getOrder(id).then(response => {
this.orders = response.data
}).catch(error => {
console.log(error)
});
}
so i'm trying to learn more about Redux through React-Native.
i'm trying to issue a HTTPS request with Axios to pull data from a web-server. everything runs fine, i console log the action and the payload is the data i need. but it still throws a 'Cannot read property 'data' of null' TypeError.
the following is my code:
import React, { Component } from 'react';
import ReduxThunk from 'redux-thunk';
import { StackNavigator } from 'react-navigation';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reducers from '../reducers';
import ReduxTestObj from '../components/ReduxTestObj';
export default class ReduxTest extends Component {
render() {
return (
<Provider store={createStore(reducers, {}, applyMiddleware(ReduxThunk))}>
<ReduxTestObj />
</Provider>
);
}
}
Here is the ReduxTestObj
import React, { Component } from 'react';
import _ from 'lodash';
import { View } from 'react-native';
import { connect } from 'react-redux';
import DevBanner from './DevBanner';
import Header from './Header';
import { actionCreator } from '../actions';
class ReduxTestObj extends Component {
componentWillMount() {
this.props.actionCreator('urlIWantToGoTo');
}
getBannerText() {
if (this.props.loading) {
return 'PULLING DATA. GIVE ME A SECOND';
}
const rObj = _.map(this.state.data[1].recipient_list);
const rName = [];
for (let i = 0; i < rObj.length; i++) {
rName[i] = rObj[i].team_key.substring(3);
}
const winnerMSG = `Teams ${rName[0]}, ${rName[1]}, ${rName[2]}, ${rName[3]} Won`;
return winnerMSG;
}
render() {
return (
<View>
<Header
text={'Redux Testing'}
/>
<DevBanner
message={this.getBannerText()}
/>
</View>
);
}
}
const mapStateToProps = state => {
return {
data: state.tba.data,
loading: state.tba.loading
};
};
export default connect(mapStateToProps, { actionCreator })(ReduxTestObj);
Here is the Action Creator
import axios from 'axios';
import { TBA_PULL } from './Types';
export const actionCreator = (url) => {
return (dispatch) => {
axios({
method: 'get',
url,
responseType: 'json',
headers: {
'Auth-Key':
'Hidden For Obvious Reasons'
},
baseURL: 'theBaseUrlOfTheWebsite'
}).then(response => {
dispatch({ type: TBA_PULL, payload: response.data });
});
};
};
And Here is the Reducer
import { TBA_PULL } from '../actions/Types';
const INITIAL_STATE = { data: [], loading: true };
export default (state = INITIAL_STATE, action) => {
console.log(action);
switch (action.type) {
case TBA_PULL:
return { ...state, loading: false, data: action.payload };
default:
return state;
}
};
As stated above, the console.log(action) prints out and the data it has is correct. yet it continues to throw the following error:
Error1
I've tried changing things around, googling, searching, gutting out the Action Reducer to make it as basic as possible by just returning a string. and it refuses to work.
Has anyone run into an issue similar to this or know how to fix it?
Thank you for your time.
EDIT: i also console logged 'this' as the first line of getBannerText() in ReduxTestObj and it returned successfully this.props.data as the data i want and this.props.loading as false. Yet it still throws the same error.
Welp. I guess i was just making a mistake.
i was calling This.state.data instead of this.props.data in getBannerText().
that solved the issue.
For vue-axios auth by api_token i use helper file api.js.
i got error - Uncaught TypeError: Cannot read property 'getters' of undefined.
I think api.js helper does not see global storage - Vuex $store.
In other components i do not need import Vuex storage, he avalaible in any place of app.
How use this.$storage in helper?
//api.js
import axios from 'axios'
let api_token = this.$store.getters.get_api_token //got error!
export function get(url) {
return axios({
method: 'GET',
url: url,
headers: {
'Authorization': `Bearer ${api_token}`
}
})
}
//Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
api_token: 'vnbnvnvnvb',
},
getters: {
get_api_token(state){
return state.api_token
}
},
});
export default store
//App.vue
import {get} from './helpers/api';
export default {
created() {
get(`/api/user/${1}`)
.then((res) => {
///do it
})
.catch((err) => {
console.log(err);
})
}
}
Found answer
// some JS file
import store from './../store'; // path to your Vuex store
let user = store.getters.user;
// do stuff with user
https://laracasts.com/discuss/channels/vue/vuex-accessing-vuex-outside-of-a-vue-component
Good evening everybody!
I'm a total beginner in React and Redux so please bear with me if this sounds totally stupid. I'm trying to learn how I can perform some API calls in Redux and it's not going all to well. When I console log the request from the action creator the promise value is always "undefined" so I'm not sure if I'm doing this correctly.
My goal is to grab the information from the data inside the payload object and display them inside the component. I've been trying to get this to work for the past days and I'm totally lost.
I'm using Axios for and redux-promise to handle the call.
Any help will be greatly appreciated.
Here's the output from the console.
Action Creator
import axios from 'axios';
export const FETCH_FLIGHT = 'FETCH_FLIGHT';
export function getAllFlights() {
const request = axios.get('http://localhost:3000/flug');
console.log(request);
return {
type: FETCH_FLIGHT,
payload: request
};
}
Reducer
import { FETCH_FLIGHT } from '../actions/index';
export default function(state = [], action) {
switch (action.type) {
case FETCH_FLIGHT:
console.log(action)
return [ action.payload.data, ...state ]
}
return state;
}
Component
import React from 'react';
import { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { getAllFlights } from '../actions/index';
import Destinations from './Destinations';
class App extends Component {
componentWillMount(){
this.props.selectFlight();
}
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
</div>
);
}
function mapStateToProps(state) {
return {
dest: state.icelandair
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ selectFlight: getAllFlights }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
axios is the promise so you need to use then to get your result. You should request your api in a separate file and call your action when the result comes back.
//WebAPIUtil.js
axios.get('http://localhost:3000/flug')
.then(function(result){
YourAction.getAllFlights(result)
});
In your action file will be like this :
export function getAllFlights(request) {
console.log(request);
return {
type: FETCH_FLIGHT,
payload: request
};
}
You can do this with thunk. https://github.com/gaearon/redux-thunk
You can dispatch an action in your then and it will update state when it gets a response from the axios call.
export function someFunction() {
return(dispatch) => {
axios.get(URL)
.then((response) => {dispatch(YourAction(response));})
.catch((response) => {return Promise.reject(response);});
};
}
I also think the best way to do this is by redux-axios-middleware. The setup can be a bit tricky as your store should be configured in a similar way:
import { createStore, applyMiddleware } from 'redux';
import axiosMiddleware from 'redux-axios-middleware';
import axios from 'axios';
import rootReducer from '../reducers';
const configureStore = () => {
return createStore(
rootReducer,
applyMiddleware(axiosMiddleware(axios))
);
}
const store = configureStore();
And your action creators now look like this:
import './axios' // that's your axios.js file, not the library
export const FETCH_FLIGHT = 'FETCH_FLIGHT';
export const getAllFlights = () => {
return {
type: FETCH_FLIGHT,
payload: {
request: {
method: 'post', // or get
url:'http://localhost:3000/flug'
}
}
}
}
The best way to solve this is by adding redux middlewares http://redux.js.org/docs/advanced/Middleware.html for handling all api requests.
https://github.com/svrcekmichal/redux-axios-middleware is a plug and play middleware you can make use of.
I took care of this task like so:
import axios from 'axios';
export const receiveTreeData = data => ({
type: 'RECEIVE_TREE_DATA', data,
})
export const treeRequestFailed = (err) => ({
type: 'TREE_DATA_REQUEST_FAILED', err,
})
export const fetchTreeData = () => {
return dispatch => {
axios.get(config.endpoint + 'tree')
.then(res => dispatch(receiveTreeData(res.data)))
.catch(err => dispatch(treeRequestFailed(err)))
}
}