VueJS: Updating data based on query variable - javascript

In my route I have a parameter like: ?id=101
And I have some data like:
data () {
return {
record: {id: null}
}
}
Now, what I want to do this: if the query parameter is present, I want to update the id in the data with the id in the query variable. I tried doing this in the fetch, as follows:
async fetch ({ store, redirect, params, query }) {
this.record = {id: query.id}
}
However, nothing happens. I also tried calling a function from the fetch, but it says the method was not defined.
Can you please help?

Ok my answer got deleted. Find the answer below:
export default {
data () {
return {
record: {
id: null
}
}
},
created () {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
fetchData () {
getRecord(this.$route.query.id, (err, id) => {
if (err) {
this.error = err.toString()
} else {
this.record.id = id
}
})
}
}
}
More info here:
https://router.vuejs.org/guide/advanced/data-fetching.html

Related

Get static props: Cannot read properties of undefined (reading 'headers')

On a dynamically generated page, I want to redirect if the user is not logged in. I would do it with getServerSideProps like this:
export async function getServerSideProps({ req, res }) {
if (req.headers['x-user-id']) {
return {
props: {
//...
}
}
} else {
return {
redirect: {
destination: '/'
}
}
}
}
However, in my dynamically generated next.js page, I need to use getStaticPaths and getStaticProps together, and you can't use getStaticProps and getServerSideProps together. Therefore, for my page [username].js, I tried doing this:
export async function getStaticProps({ params, req, res }) {
const results = await Get('https://example.com/api/getUsers')
const i = results.findIndex(e => e.username === params.username)
if (req.headers['x-user-id']) {
return {
props: {
user: results[i]
}
}
} else {
return {
redirect: {
destination: '/'
}
}
}
}
This however gives me the error:
TypeError: Cannot read properties of undefined (reading 'headers')
How can I fix this?

MongoDB struggling to update DB

I'm new to MongoDB. I have a DB where cards data will be stored and update counts if the user likes the cards. Giving me a total likes number.
I keep getting my res as a 400 and I can't work out why. I got the update method to work manually. but when I put it into a function it does not work.
I'm using NEXT JS API routes.
import dbConnect from "../../utils/dbConnect";
import FavSchema from "../../models/FavoriteModel";
dbConnect();
export default async (req, res) => {
const { method } = req;
switch (method) {
case "GET":
try {
} catch (error) {
res.status(400).json({ success: false });
}
break;
case "POST":
try {
const query = {
cardId: req.body.cardHandler,
};
await FavSchema.findOneAndUpdate(
query,
{ $inc: { favCount: 1 } },
{ upsert: true }
);
res.send("Succesfully saved.");
} catch (error) {
res.send(400, { error: "Error" });
}
}
};
function
const handleCardFavClick = (id) => {
const cardHandler = {
id,
};
fetch("/api/favcounter", {
method: "POST",
body: JSON.stringify(cardHandler),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((data) => console.log(data));
dispatch(makeFav(cardHandler));
};
Thank you!
You are passing
{ id: "<id>" }
as body in your API and reading "cardHandler" from req.body, which is "undefined".
In your POST API, replace
const query = {
cardId: req.body.cardHandler,
}
with
const query = {
cardId: req.body.id
}

How to test an async function with callback in Jest?

I'm having a hard time finding info on how to test this function:
const MyService = {
async stringify (entry, cb) {
try {
const response = await axios.post('localhost:3005/stringify', {
entry
})
cb(null, response.data)
} catch (minificationError) {
if (minificationError.response.status === 500) {
cb('error 1', null)
} else {
cb('error 2', null)
}
}
}
}
I understand I can import axios and mock the .post like this:
axios.post.mockResolvedValue({
data: { some: 'value' }
})
That'd work great if I the MyService was returning the promise... but how do I deal with the callback? Is this a bad practice and should the service be returning the promise and then handle errors in the component functions instead?
Additionally, how would I mock a status code with jest (to test the failed states?)
First, you have to set up mock axios after that you have to call your mockapi's in your test case
const axios = {
post: jest.fn(() => {
return Promise.resolve({
data: {},
});
}),
create: () => axios,
request: {},
defaults: {
adapter: {},
headers: {},
},
interceptors: {
request: {
use() {},
},
response: {
use() {},
},
},
};
Once you setup mock axios then you can access in your test case and return whatever mock response and status code you want.
mockAxios.post.mockImplementation((url) => {
if (url.includes("something")) {
return Promise.resolve({ data:{"response":""}, status: 200 });
}
return Promise.reject(new Error("not found"));
});

Vue.js and Axios: Transform Request returns undefined data

I was trying to use transformRequest and transformResponse in order to display a loader while data is rendering. When I have done this, it worked perfectly but it is appeared that my POST and PATCH requests are not processed properly now. There are no error messages on console but when I try to modify some entity (and send PATCH request), nothing happens. When I delete transformRequest function, I can send POST and PATCH.
Can somebody explain what I did wrong?
UPDATE! Here is what I added in http/index.js:
...
transformRequest(data) {
console.log(data); // returns undefined
store.dispatch('loadingData');
console.log(data) // returns undefined
return console.log(JSON.stringify(data)); // returns undefined
},
transformResponse(data) {
store.dispatch('finishLoadingData');
const parsedData = JSON.parse(data);
if (parsedData.error === 'Access denied') {
cookies.remove('access_token');
window.location = `${config.mainSite}/login`;
}
return parsedData;
},
...
Here is the store:
export default {
state: {
loading: false,
},
actions: {
loadingData({ commit }) {
commit('LOADING_DATA');
},
finishLoadingData({ commit }) {
commit('FINISH_LOADING_DATA');
},
},
mutations: {
LOADING_DATA(state) {
state.loading = true;
},
FINISH_LOADING_DATA(state) {
state.loading = false;
},
},
getters: {
getLoading(state) {
return state.loading;
},
},
};
As we use Axios, transformRequest and transformResponse accepts an array of functions and not a single function. Can you try this:
...
transformRequest: [(data) => {
store.dispatch('loadingData');
return data;
}],
transformResponse: [(data) => {
store.dispatch('finishLoadingData');
const parsedData = JSON.parse(data);
if (parsedData.error === 'Access denied') {
cookies.remove('access_token');
window.location = `${config.mainSite}/login`;
}
return parsedData;
}],
...

VueJS: Fetch data before and after loading a component

I am new to VueJS and working on a component and want to fetch some data from an API before the corresponding route is loaded; only then the component should load. Once the component is created, I have to call another API that takes as input the data obtained from first API. Here is my component script:
export default {
name: 'login',
data () {
return {
categories: []
}
},
created () {
// it gives length = 0 but it should have been categories.length
console.log(this.categories.length);
// Call getImage method
loginService.getImage(this.categories.length)
.then(res => {
console.log('Images fetched');
})
},
beforeRouteEnter (to, from, next) {
loginService.getCategories().then((res) => {
next(vm => {
vm.categories = res.data.categories;
});
}, (error) => {
console.log('Error: ', error);
next(error);
})
},
methods: {}
}
I tried using mounted hook but it does not work. However if I watch the categories property and call fetch image method, it works. I don't think using watchers is the best approach here. Any thoughts?
Move your call to get additional information into a method and call that method from next.
export default {
name: 'login',
data () {
return {
categories: []
}
},
beforeRouteEnter (to, from, next) {
loginService.getCategories().then((res) => {
next(vm => {
vm.categories = res.data.categories;
vm.getMoreStuff()
});
}, (error) => {
console.log('Error: ', error);
next(error);
})
},
methods: {
getMoreStuff(){
console.log(this.categories.length);
// Call getImage method
loginService.getImage(this.categories.length)
.then(res => {
console.log('Images fetched');
})
}
}
}
Alternatively, do it in the callback for getCategories.
loginService.getCategories()
.then(res => {
vm.categories = res.data.categories;
loginService.getImage(vm.categories.length)
.then(res => //handle images then call next())
})
.catch(err => //handle err)
Or if you are using a pre-compiler that handles async/await
async beforeRouteEnter(to, from, next){
try{
const categoryResponse = await loginService.getCategories()
const categories = categoryResponse.data.categories
const imageResponse= await loginService.getImage(categories.length)
next(vm => {
vm.categories = categories
vm.images = imageResponse.data.images
})
} catch(err){
//handle err
}
}

Categories

Resources