TypeError: Cannot read properties of undefined (reading '$router'), what is this error about? How can I fix this? - vue.js

$Happy New Year! So, I'm setting up a redirect after an authentication token retrieval and I keep getting "TypeError: Cannot read properties of undefined (reading '$router')" in the console and the user is not redirected to the desired page ("/dashboard"). I'm outsourcing the authentication to a dataRequests.user.js file that then goes to a vue component. Thanks in advance. Here is the code:
import common from "./dataRequests.commons";
import { login, inputLogin, inputPassword } from '/src/pages/Index.vue'
let userRequest = {}
userRequest.authenticate = (inputLogin, inputPassword) => {
return new Promise(() => {
let axios = require("axios");
let config = {
method: 'post',
baseURL: common.baseURL + '/auth/login',
headers: {
'Content-Type': 'application/json',
},
data : {
login: inputLogin,
password: inputPassword,
}
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.then(() => this.$router.push(this.$router.redirect || '/dashboard'))
.catch(function (error) {
console.log(error);
//console.log('input login', this.inputLogin)
//console.log('input password', this.inputPassword)
});
console.log('input login', inputLogin)
console.log('input password', inputPassword)
});
}
export default userRequest;

Something like this:
import common from "./dataRequests.commons";
import { login, inputLogin, inputPassword } from '/src/pages/Index.vue'
import axios from 'axios'
import router from 'router'
let config = {
method: 'post',
baseURL: common.baseURL + '/auth/login',
headers: {
'Content-Type': 'application/json',
}
userRequest.authenticate = (inputLogin, inputPassword) => {
const apiClient = axios.create(config)
return new Promise(() => {
apiClient.post(data : {
login: inputLogin,
password: inputPassword,
})
.then(() => router.push...etc

Related

react native laravel echo: can not find variable pusher

i have imported laravel-echo and #pusher/pusher-websocket-react-native in react native but error occur:can not find variable pusher
please tell me solution will be thankfully
import Echo from "laravel-echo";
import {
Pusher,
PusherMember,
PusherChannel,
PusherEvent,
} from '#pusher/pusher-websocket-react-native';
let echo = new Echo({
broadcaster: "pusher",
key: "123",
wsHost: "my-domain",
wsPort: 6001,
forceTLS: false,
cluster: "mt1",
disableStats: true,
authorizer: (channel, options) => {
console.log(options);
return {
authorize: async (socketId, callback) => {
console.log('socketId, callback',channel,socketId, callback)
const response = await fetch(`http://my-domain/api/broadcasting/auth`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
ContentType: 'application/json'
},
data: {
socket_id: socketId,
channel_name: channel.name,
},
})
.then((response) => {
console.log('fd',response);
callback(false, response.data);
})
.catch((error) => {
console.log('test',error)
callback(true, error);
});
},
};
},
});
=============================================================================================================================================
You must define Pusher to window
window.Pusher = Pusher;
Just write this line below the import

data sent with vuex action return undefined

i'm using axios with vuex, i need to send data with json form to execute post request and add new row with axios, i'm using vuex, when action is trigered it doesn't keep the data and sent it on action, the data json is created on vue componment but don't send it to action to execute axios post :
Action.js:
export const addClassification = ({data}) => {
console.log('data actio:', {data})
axios
.post("/vendor/classification/save", data, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
// commit("ADD_TO_CLASSIFICATION", data);
})
.catch((err) => {
console.log(err);
});
state.js:
export default {
vendorClassificationList: [],
}
page.vue:
<BaseButton
label="Modifier"
classValue="btn-outline-primary"
#click.native="addClassificationData"
/>
data() {
return {
submitStatus: "",
name: this.$route.params.name,
id: this.$route.params.id,
code: this.$route.params.code,
jsonData:[]
};
},
methods: {
...mapActions(["addClassification"]),
addClassificationData() {
this.jsonData = JSON.stringify({
id: null,
name: this.name,
code:this.code,
active:true
})
console.log('json is', this.jsonData)
this.addClassification({
data : this.jsonData
})
},
Actions is Vuex receive the vuex context as the first param, as you can see in the docs.
In other words if you change in Action.js:
addClassification = ( {data}) => {
to
addClassification = (vuexContext, {data}) => {
it should do the trick. You can call the param vuexContext, context, destructure it if needed or call it _ if unused (as in your case), doesn't really matter, as long as it's there.
Your vuex action is wrong. You are missing the context which can use argument restructuring. Also, you probably need to send res.data within the commit instead of res, depending on what are you doing in your mutation.
actions: {
addClassification ({ commit }, payload) {
axios
.post("/vendor/classification/save", payload, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
commit("ADD_TO_CLASSIFICATION", res.data);
})
.catch((err) => {
console.log(err);
})
}
}

How to send axios reques in react native?

I'm new to React Native and I'm trying to send axios request to my backend but I'm stuck in it.
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
const res = await axios.post(`http://localhost:8000/auth/jwt/create/`, body, config);
console.log('kk');
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(load_user());
};
when it tries to post request through axios it gives following error.
although I haved tried this in React JS and it's working perfectly.
please help me to solve this in react native
Per the React Native Networking Docs, React Native supports the fetch web API for sending requests. I advise you use fetch instead of axios as it has all of the same features without any added bloat and overhead. Here is a port of your code to use fetch:
export const login = (email, password) => async (dispatch) => {
const res = await fetch(`http://localhost:8000/auth/jwt/create/`, {
method: "POST", // this signnifies POST request type
body: JSON.stringify({ email, password }), // still including the body
headers: {
// apply the headers
"Content-Type": "application/json"
}
});
const data = await res.json(); // parses the body as a json object
console.log("kk");
dispatch({
type: LOGIN_SUCCESS,
payload: data
});
dispatch(load_user());
};
Try to use this way:
// define axios request
import axios from 'axios';
const request = axios.create({
baseURL: 'https://url.com/api/v1',
timeout: 20000,
});
request.interceptors.request.use(
config => {
// config.headers.Authorization = `Bearer ${token}`;
config.headers.Accept = 'Application/json';
return config;
},
error => {
//return Promise.reject(error);
console.log("interceptors.request: ", error);
return false;
},
);
request.interceptors.response.use(
response => {
if (response && response.data) {
return response.data;
}
return response;
},
error => {
console.log('Response error: ', error);
//throw error;
return false;
},
);
export default request;
Usage:
import request from '../';
export const getAPI = () => {
return request({
url: '/getData',
method: 'GET',
// ...
});
};
getAPI().then(response => {
//...
});

Axios interceptor is not getting the current user auth token from vuex store

I'm using Axios to send user input to DRF api and it returns an auth token. I'm saving the token in vuex store. In another component. I'm trying to request another api endpoint with Axios with the latest token in the request headers. The issue I'm having is that Axios will either send the request with no token at all or with the token of the previous user that was logged in. It does not get the current token from the vuex store. I used Axios interceptors hoping that would help but it did not.
Login.vue
<script>
export default {
name: 'Login',
data () {
return{
email: null,
password: null,
token: '',
}
},
props: {
},
methods: {
submitForm () {
this.$store.dispatch('loginUser',{
email: this.email,
password: this.password
}).then(() =>{
this.$router.push({ name: 'List' })
}) .catch(err =>{
console.log(err)
})
},
}
}
</script>
store/index.js
import axios from 'axios'
import { createStore } from 'vuex'
export default createStore({
state: {
token: localStorage.getItem('token'),
},
mutations: {
getToken(state, token) {
localStorage.setItem('token', token)
state.token = token
}
},
actions: {
loginUser({ commit }, data){
axios({
method: 'POST',
url: 'http://localhost:8000/auth/login/',
headers: {'Content-Type': 'application/json'},
data: {
'email': data.email,
'password': data.password,
}
}).then(response =>{
commit('getToken', response.data['key'])
})
}
},
modules: {
}
})
List.vue
<script>
import axios from 'axios'
import store from '/src/store'
export default {
name:'List',
data () {
return {
entry: []
}
},
created() {
axios.interceptors.request.use(function (config){
let token = store.state.token
config.headers['Authorization'] = 'Token ' + token;
return config;
})
axios({
method: 'GET',
url: 'http://localhost:8000/journal/',
headers: {'Content-Type': 'application/json'},
}).then(response =>{
this.entry = response.data
}) .catch(err =>{
console.log(err)
})
}
}
</script>
I thought the point of the interceptor was to get the token before actually making the get request, but it does not seem to be doing that.
Not exactly sure why this works but rewriting my loginUser action like this solves my issue.
actions: {
loginUser({ commit }, data){
return new Promise ((resolve, reject) => {
axios({
method: 'POST',
url: 'http://localhost:8000/auth/login/',
headers: {'Content-Type': 'application/json'},
data: {
'email': data.email,
'password': data.password,
}
}).then(response =>{
commit('getToken', response.data['key'])
resolve()
}).catch(err => {
reject(err)
})
})
}
},
I think it's because return new Promise basically interrupts the the initial promise in Login.vue making sure the client doesn't make an api request without the correct token from the server but I'm not sure.

React Native: setState doesn't work when calling try-catch function

I tried to call APP with this code imported from another file and it worked fine:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
let formData = new FormData();
formData.append('userId', '1'); // < this is what I want to change
formData.append('key', '***'); //my key
export function getScoreFromAPI () {
return fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
}
but now I want to change my userId from 1 to an constante from Asyncstorage, so I decide to change my code to this:
constructor(props) {
super(props)
this.state = { infos: [], userId: '' }
}
componentWillMount() {
this.getScoreFromAPI().then(data => {
this.setState({ infos: data })
});
console.log(this.state.infos);
AsyncStorage.getItem(USERID_STORED)
.then((data) => {
if (data) {
this.setState({userId:data})
}
});
}
async getScoreFromAPI() {
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
try {
let response = await fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
let res = await response.json();
} catch(error) {
console.warn("errors are " + error);
}
};
with a try-catch function but when I call getScoreFromAPI() in ComponentWillMount() I can't setState with received data, I still have an empty array in info:[]
my questions:
how can I replace '1' in userId by a value in asyncstorage in the first file ?
if it isn't possible, what I have do to setState info: [] with my data reveived
I've simplified your code into a promise chain in which calling getScoreFromAPI will execute after getting the userId from AsyncStorage, then storing the response into the infos state, while returning null if there was an error, and logging the error to the console. The data was not previously returned from getScoreFromAPI, so the value would always become null. I have not tested this code, but this should give you a good base to work from:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
export default class Test {
constructor() {
this.state = {
infos: null,
userId: ''
};
}
componentDidMount() {
AsyncStorage.getItem(this.state.userId)
.then(userID => {
this.setState({ userId: userID || '' });
})
.then(() => {
return this.getScoreFromAPI();
})
.then(data => {
this.setState({ infos: data });
})
.catch(console.error);
}
getScoreFromAPI = () => {
const formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(response => {
// use response data here
return response.json();
})
.catch(e => {
console.error(e);
return null;
});
};
}
You're doing your API call before fetching your value from AsyncStorage (I know this is async but it's not very readable if you do it that way).
getScoreFromAPI doesn't return anything, that's why your setState isn't working.
You don't need to use try and catch here, promises have their own error handling mechanism (the .catch() method).
I think callbacks are more readable and lead to less bugs than using .then() in code.
This is how I would do it:
constructor(props)
{
super(props);
this.state = { infos: [], userId: '' };
this.onSuccess = this.onSuccess.bind(this);
this.onFailure = this.onFailure.bind(this);
}
componentWillMount()
{
// Get userID from local storage, then call your API
AsyncStorage.getItem(YOUR_KEY)
.then(userID=> {
if (userID)
{
this.setState({ userId : userID }, () => {
this.getScoreFromAPI(this.onSuccess, this.onFailure);
});
}
});
}
onSuccess(data)
{
this.setState({
infos : data
});
}
onFailure(err)
{
console.warn('Error ' + err);
}
getScoreFromAPI(onSuccess, onFailure)
{
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //your key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(res => res.json())
.then(json => {
onSuccess(json);
})
.catch(err => {
onFailure(err);
});
}
It's finally done. I tried this and it worked. Thank you to all of you
this is what I have done:
...
const USERID_STORED = "userid_stored";
const GSM_STORED = "gsm_stored";
...
class ScoreList extends React.Component {
constructor(props) {
super(props)
this.state = { infos: [], userId: '', gsmStored: '', }
}
componentWillMount() {
AsyncStorage.getItem(USERID_STORED)
.then(userId => {
this.setState({ userId: userId});
this.getScoreFromAPI(this.state.userId).then(data => {
this.setState({ infos: data });
});
});
AsyncStorage.getItem(GSM_STORED)
.then(gsmStore => {
this.setState({ gsmStored: gsmStore});
});
}
getScoreFromAPI (userId) {
let formData = new FormData();
formData.append('userId', userId);
formData.append('key', '***');
return fetch('https://***',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
};