Firebase, trying to pull the collection based on a ID? - reactjs

Basically, I have two collections per post. One with the comments on the post and one with the post information. The formula I wrote gives me the data of the post information. I want it to return both collections so I can map through the comment collection. but I cannot seem to figure out how to get it to send me to one level up basically. Any help would be appreicated!
const docRef = doc(db, "posts", postId);
useEffect(() => {
if(postId){
const getUsers = async () => {
const data = await getDoc(docRef)
console.log(data.data())
}
getUsers()
}
}, [])
The answer I was looking for is as follows!
const stepOne = collection(db,"posts")
const stepTwo = doc(stepOne,postId)
const stepThree = collection(stepTwo,"comments")
const stepFour = onSnapshot(stepThree,((snapshot)=>snapshot.docs.map((doc)=>console.log(doc.data()))))

Through this structure on the picture, comments are a collection nested inside posts, right? If so, then you cannot return a subcollection from a simple query on the parent document. Try fetching the post info first, then fetch the comments from an other query
this is for posts:
const docRef = doc(db, "posts", postId);
the path for comment will be
"posts/postId/comment"

Related

How to build query in React MERN stack

I use the MERN stack and I want to create something like this on the frontend: http://localhost:3000/products?color=0000&sort=latest&category=man etc.
I'm using the redux toolkit and my getProductSlice looks like this:
export const getProducts = createAsyncThunk(
'product/get',
async ({ page, sort, localValue, colorFilter, categoryFilter }, thunkAPI) => {
let colorStr = colorFilter.substring(1);
let url = `/api/v1/products?page=${page}&sort=${sort}&color=${colorStr}&cat=${categoryFilter}`;
if (localValue) {
url = url + `&search=${localValue}`;
}
try {
const { data } = await axios.get(url);
return data;
} catch (error) {
const message = error.response.data.msg;
return thunkAPI.rejectWithValue(message);
}
}
);
Every filter works great, in the backend I return products depending on which filter is applied. I dont know how to build query in frontend and when i enter that url i want to filters to be applied based on url.
To build a query string in the frontend and apply filters based on the query string in the URL, you can do the following:
1 Parse the query string from the URL using the URLSearchParams API:
const searchParams = new URLSearchParams(window.location.search);
Extract the values of the filters from the query string using the get method of URLSearchParams:
const color = searchParams.get('color');
const sort = searchParams.get('sort');
const category = searchParams.get('category');
Use the extracted filter values to create a payload object for the getProducts async thunk:
const payload = {
page: 1, // or whatever page you want to start from
sort,
localValue: '', // or whatever value you want to use for the localValue filter
colorFilter: color,
categoryFilter: category
};
Dispatch the getProducts async thunk with the payload object:
dispatch(getProducts(payload));
This should apply the filters based on the query string in the URL when the getProducts async thunk is dispatched.

How to fetch with parameters using React Query?

For the sake of this question let's first assume existence of such entity:
export interface Event {
id: number;
date: Date;
}
Then let's assume there's backend with such endpoints:
GET /events -> returns all events
GET /events?startDate=dateA&endDate=dateB -> returns all events between dateA and dateB
I create hook containing 4 methods (one for each CRUD operation) in my frontend code like this:
export function useEvents() {
const getEvents() = async () => {
const response = await axios.get(`events`);
return response.data;
}
const postEvent()...
const updateEvent()...
const deleteEvent()...
const query = useQuery('events', getEvents);
const postMutation = ...
const updateMutation = ...
const deleteMutation = ...
return { query, postMutation, updateMutation, deleteMutation }
}
This architecture works like a charm but I got to the point where I would like to conditionaly fetch events based on currently chosen month in my Calendar.tsx component.
How would I inject this information into useQuery() and getEvents()?
the query key should contain all "dependencies" that you need for your fetch. This is documented in the official docs here, and I've also blogged about it here.
So, in short:
const getEvents(month) = async () => {
const response = await axios.get(`events/${month}`);
return response.data;
}
const query = useQuery(['events', month], () => getEvents(month));
The good thing is that react-query will always refetch when the key changes, so data for every month is cached separately, and if the month changes, you'll get a fetch with that month.

How to share data from useState in React to another Component

Hey guys let me quickly explain my problem.
I currently have Component in which User can Search something. And after they Click on a Button I get the Data from Firebase which is then stored in a useState which I map afterwards. This whole operation is in one function.
But for now I show the result at the same Page because I dont know how to transfer the data in the useState to the other component.
const handleClick = async () => {
const kurzRef = collectionGroup(db, 'kurzwaffensub' );
const MOD = query(kurzRef,where("kurzModell", "==", `${kurzModell}` ));
if(kurzModell) {
const getWaffenDaten = async () => {
const modell = await getDocs(MOD);
const data = [];
for (const doc of modell.docs) {
const parentDoc = await getDoc(doc.ref.parent.parent);
const { Name, avatar,avatarPath, Erfahrung, Adresse, Schützenverein } = parentDoc.data();
const waffenbilderRef = collection(db, 'users', doc.data().uid, 'waffenbildersub')
const subCollectionDocs = await getDocs(waffenbilderRef)
const subCollectionData = subCollectionDocs.docs.map((doc) => {
return { id: doc.id, ...doc.data()}
})
data.push({
...doc.data(),
Name,
subCollectionData,
avatar,
avatarPath,
Erfahrung,
Adresse,
Schützenverein
});
}
setTest(data)
}
getWaffenDaten()
}
After that operation I just return the Result in the same Page . And I want to change the page after the onClick event with the Result. Because I dont want to see the User Interface of the Search Component.
Perhabs its pretty simple but Im still a beginner and would be very glad if you can help me out and teach me something new and important.
You can do this in multiple ways:
You can pass search query as URL parameter if you using router and fetch the data from result page
You can use state management tool like Redux or built in context api.

How I can display only one object from API array Reactjs

How I can display only one object from [data.hits]? Ive tried map(), filter, also setRecipes([data.hits.recipe[0]]); etc ... and it doesn't work. Currently, it shows 10 objects on the website but I need only one. Thank you for any help.
const [recipes,setRecipes] = useState ([]);
useEffect(()=>{
getReciepes();
},[query]);
const getReciepes = async () => {
const response = await fetch (`https://api.edamam.com/search?
q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`);
const data = await response.json();
setRecipes(data.hits);
console.log(data.hits);}
I dont know how I did not notice this. Here is a simple solution :
const list=[...data.hits]
list.length = 1
setRecipes(list);
console.log(list);
}

how to get both values of ORDER and OrderItems

I am trying to fetch data from Firebase Cloud Firestore and load it into my ReactJS app upon loading into the browser.
In this code, I only get the value of ORDER.
How to get both the values ORDER and OrderItems?
componentDidMount() {
firestore
.collection('ORDERS')
.get()
.then((querySnapshot) => {
const ORDERS = [];
querySnapshot.forEach((doc) => {
const data = doc.data();
ORDERS.push(data);
});
this.setState({ ORDERS: ORDERS });
})
.catch((error) => console.log(error));
}
how to get both the values
Fetching items from a sub-collection
You are currently fetching the items from the ORDERS collection. You can take an order document and fetch the orderItems within it by using a reference.
I've used async/await. However, you can easily convert this to use promises.
// Set the reference for the order document
const orderRef = firestore.collection('ORDERS').doc(orderId);
// Fetch the document and extract the data
const orderDS = await orderRef.get();
const orderData = orderDS.data();
// Fetch the orderItems and add them to an array
const orderItemsQS = await orderRef.collection('orderItems').get();
const orderItems = orderItemsQS.docs.map(orderItemQDS => (
const {id, ref, path} = orderItemsQDS; // You can add one or more of these to make it easy to update values back into Firestore
const data = orderItemsQDS.data();
return {id, ref, path, data};
));
You can either fetch these as you use your forEach and push or (recommended) only fetch orderItems when a user has selected an ORDER.
Alternative document references
Option 1
const orderRef = firestore.collection('ORDERS').doc(orderId);
const orderItemsQS = await orderRef.collection('orderItems).get();
Option 2
const orderItemsQS = await firestore
.collection('ORDERS').doc(orderId)
.collection('orderItems').get();
Option 3
const orderItemsQS = await firestore.collection(`ORDERS/${orderId}/orderItems`).get();
Naming conventions
I add the following suffixes to my variable names to make them easier to read:
QS = QuerySnapshot
QDS = QueryDocumentSnapshot
DS = DocumentSnapshot
Javascript reference
This is a really useful resource to help you when getting started.
https://firebase.google.com/docs/reference/js/firebase.firestore

Resources