Can't fetch data with react-query - react-query

On my client-side(React js), I want to fetch data from the backend. But it's not working. The output of data is undefiend. Code Snippets
const url = `http://localhost:5000/items/${id}`;
const { data } = useQuery("data", () => axios(url));
console.log("data", data);
In the backend, I am using Express js and MongoDB as databases.

Try creating a function for fetching, for example:
const fetchData = async (id) => {
try {
const URL = `http://localhost:5000/items/${id}`;
const response = await axios.get(URL);
return response;
} catch(error) {
console.log(error);
}
}
Then:
const { data } = useQuery("data", () => fetchData(id));
You have to provide the id to fetchData

Related

use Effect not working to bring up my product, using axios use params,

This code is not working for me i am trying to pull data from my mongodb
const ProductScreen = ({ match }) => {
const [product, setProduct] = useState({});
const { id } = useParams();
useEffect(() => {
const fetchProduct = async () => {
const { data } = await axios.get(
`/api/product/${encodeURIComponent(id)}`
);
setProduct(data);
};
fetchProduct();
}, []);
};
pull data from server of mongo db
It is possible when the component first mounts, id is null and useParams() doesn't get it till the second render. So add an if statement in your useEffect to make sure the id is present. Also add id to the dependency array, so if the id changes, you will refetch the data for it. Otherwise, with an empty dependency array, the useEffect will only run on first mount.
const ProductScreen = ({ match }) => {
const [product, setProduct] = useState({});
const { id } = useParams();
useEffect(() => {
const fetchProduct = async () => {
const { data } = await axios.get(
`/api/product/${encodeURIComponent(id)}`
);
setProduct(data);
};
if (id) {
fetchProduct();
}
}, [id]);
};

How can I get Firebase Storage downloadable array of links and set it to object for storing in mongodb database?

My question is how do I set array of image links to my createAd function for storing the result into MongoDB database. Console log gives the getLinks result array as below. However, always I'm getting empty [] array for photos[] field in MongoDB database collection.
getlink function do the upload image to firestore and get downloadable url
const getLinks = (values) => {
const array = [];
values.adImgs.map((image: any) => {
const imgPath = `ad_images/${image.name + v4() }`;
const imageRef = ref(storage, imgPath);
uploadBytes(imageRef, image).then((snapshot) => {
getDownloadURL(snapshot.ref)
.then((url)=> array.push(url));
})
});
return array;
}
This is the function to store data into MongoDb database
const createAdd = async (values) => {
const newObj: any = {
title: values.title,
photos: getLinks(values)
}
await createPost(newObj);
}
The uploadBytes() and getDownloadURL() functions both return a promise. You are returning an empty before waiting for the files to upload. Try refactoring the code as shown below:
// async function
const getLinks = async (values) => {
const uploadPromises = values.adImgs.map((image) => {
const imgPath = `ad_images/${image.name + v4() }`;
const imageRef = ref(storage, imgPath);
return uploadBytes(imageRef, image);
})
// Upload all images
const res = await Promise.all(uploadPromises);
const links = await Promise.all(res.map((r) => getDownloadURL(r.ref)));
return links;
}
const createAdd = async (values) => {
const newObj: any = {
title: values.title,
photos: await getLinks(values) // <-- add await
}
await createPost(newObj);
}

How to use axios to `fetch all()`

I don't understand how to use axios to fetch data from an array of urls. But I can do it with fetch. The following code works perfectly:
const url = 'https://vimeo.com/api/oembed.json?url='
async index(videoUrls = []) {
try {
const response = await Promise.all(
// videoUrls.map(videoUrl => axios.$get(`${url}${encodeURIComponent(videoUrl)}`))
videoUrls.map(videoUrl => fetch(`${url}${encodeURIComponent(videoUrl)}`))
)
const results = await Promise.all(response.map(r => r.json()));
return results;
} catch (e) {
console.error(e)
}
}
When I make a call like index(["https://vimeo.com/216850224", "https://vimeo.com/642263700"]), my console shows an array with all the video meta details vimeo has to give me. This is perfect.
But the moment I comment out the line that uses fetch and use axios, I get a CORS error.
What is the idiomatic way to fetch data from a bunch of urls in axios?
EDIT
I also tried this, but the .all() function doesn't seem to exist
async index(videoUrls = []) {
try {
const response = await axios.all(videoUrls.map(videoUrl => `${url}${encodeURIComponent(videoUrl)}`));
return response;
} catch (e) {
console.error(e)
}
}
You can easily do it like below:
(async function getAll() {
const axiosrequest1 = axios.get('https://jsonplaceholder.typicode.com/posts');
const axiosrequest2 = axios.get('https://jsonplaceholder.typicode.com/posts');
const axiosrequest3 = axios.get('https://jsonplaceholder.typicode.com/posts');
const [res1, res2, res3] = await Promise.all([axiosrequest1, axiosrequest2, axiosrequest3]);
console.log('request1', res1.data);
console.log('request2', res2.data);
console.log('request3', res3.data);
})();
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
The Axios version would be slightly different because it automatically decodes and embeds the response body into the response.data property (no need for res.json())
const baseUrl = "https://vimeo.com/api/oembed.json"
const index = async (videoUrls = []) => {
// create an array of responses and wait for them to resolve
const responses = await Promise.all(
videoUrls.map(url => axios.get(baseUrl, { params: { url } })
)
// extract the `data` properties and return them as an array
return responses.map(({ data }) => data)
}
Exactly when you extract response.data is totally up to you. It could also look like this
const index = (videoUrls = []) => Promise.all(
videoUrls.map(async (url) => (
await axios.get(baseUrl, { params: { url } })
).data)
)
FYI, your fetch() version could be a little cleaner too...
const baseUrl = "https://vimeo.com/api/oembed.json"
const index = (videoUrls = []) => Promise.all(
videoUrls.map(async (url) => {
const params = new URLSearchParams({ url })
const res = await fetch(`${baseUrl}?${params}`)
if (!res.ok) { // check for bad response
throw new Error(`${res.status}: ${await res.text()}`)
}
return res.json()
})
)

How to fetch file from mongodb gridfs using GraphQL?

I completed file upload now I want to fetch file from mongodb using graphql. I have tried to fetch chunks of file and then merge it but it not worked as I expected.
So how to fetch entire file from mongodb inside graphql Query?
Here i'm returning bas64 as string of image which is not preferable for larger file size
const downloadFile = async (fileId) => {
const bucket = new mongoose.mongo.GridFSBucket(mongoose.connection.db, {
bucketName: 'files',
});
return new Promise((resolve, reject) => {
// temporary variable to hold image
var data = [];
// create the download stream
const readstream = bucket.openDownloadStream(new ObjectID(fileId));
readstream.on('data', function (chunk) {
data.push(chunk);
});
readstream.on('error', async (error) => {
reject(error);
});
readstream.on('end', async () => {
let bufferBase64 = Buffer.concat(data);
const img = bufferBase64.toString('base64');
resolve(img);
});
});
};
And this is query for fetching image
async getImage(_, { fileId }) {
try {
const img = await downloadFile(fileId);
return img;
} catch (error) {
throw new Error(error);
}
},

Connect Apollo with mongodb

I want to connect my Apollo server with my mongoDB. I know there are many examples out there, but I get stuck at the async part and did not found a solution or example for that (that's strange, am I completly wrong?)
I started with the example from next.js https://github.com/zeit/next.js/tree/master/examples/api-routes-apollo-server-and-client .
But the mongodb integration is missing.
My code
pages/api/graphql.js
import {ApolloServer} from 'apollo-server-micro';
import {schema} from '../../apollo/schema';
const apolloServer = new ApolloServer({schema});
export const config = {
api: {
bodyParser: false
}
};
export default apolloServer.createHandler({path: '/api/graphql'});
apollo/schema.js
import {makeExecutableSchema} from 'graphql-tools';
import {typeDefs} from './type-defs';
import {resolvers} from './resolvers';
export const schema = makeExecutableSchema({
typeDefs,
resolvers
});
apollo/resolvers.js
const Items = require('./connector').Items;
export const resolvers = {
Query: {
item: async (_parent, args) => {
const {id} = args;
const item = await Items.findOne(objectId(id));
return item;
},
...
}
}
apollo/connector.js
require('dotenv').config();
const MongoClient = require('mongodb').MongoClient;
const password = process.env.MONGO_PASSWORD;
const username = process.env.MONGO_USER;
const uri = `mongodb+srv://${username}:${password}#example.com`;
const client = await MongoClient.connect(uri);
const db = await client.db('databaseName')
const Items = db.collection('items')
module.exports = {Items}
So the problem is the await in connector.js. I have no idea how to call this in an async function or how to provide the MongoClient on an other way to the resolver. If I just remove the await, it returns – obviously – an pending promise and can't call the function .db('databaseName') on it.
Unfortunately, we're still a ways off from having top-level await.
You can delay running the rest of your code until the Promise resolves by putting it inside the then callback of the Promise.
async function getDb () {
const client = await MongoClient.connect(uri)
return client.db('databaseName')
}
getDb()
.then(db => {
const apollo = new ApolloServer({
schema,
context: { db },
})
apollo.listen()
})
.catch(e => {
// handle any errors
})
Alternatively, you can create your connection the first time you need it and just cache it:
let db
const apollo = new ApolloServer({
schema,
context: async () => {
if (!db) {
try {
const client = await MongoClient.connect(uri)
db = await client.db('databaseName')
catch (e) {
// handle any errors
}
}
return { db }
},
})
apollo.listen()