I have a problem with taking data from reference data.
The code below is component I made to get Data from Firebase Database. When I executed this, I could get Buses data. Plus, I checked that Users data(Reference) belongs to a bus. However, When I coded to get a user's name, phone, or uuid it failed. What is the reason and How can I resolve it?
import { StyleSharp } from "#mui/icons-material";
import React, { useEffect } from "react";
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '../../app/store'
import BusTable from "../../components/BusTable";
import BusTabs from "../../components/Tab";
import { collection, query, onSnapshot } from 'firebase/firestore'
import { db } from './../../app/firebase/FirebaseConfig'
import styles from "./index.module.css";
import { setBuses } from "./../../features/buses/busesSlice";
import { Bus as BusData } from './../../app/firebase/collections/Bus'
const Bus = () => {
const buses = useSelector((state: RootState) => state.buses.buses)
const dispatch = useDispatch()
useEffect(() => {
const q = query(collection(db, 'trips', '5DpHAkIuOpoPZSTzNc5A', 'bus'))
const unsub = onSnapshot(q, (querySnapshot) => {
const buses = new Array(0)
querySnapshot.forEach((doc) => {
buses.push(new BusData(doc.id, '', 1, doc.data().users))
})
dispatch(setBuses({buses: buses}))
console.log(buses) /////SUCCESS TO GET BUSES DATA/////
})
return unsub
}, [dispatch]);
return (
<div>
{buses.map((bus) => (
<div className={styles.busTabs}>
{bus.users.map((user)=>(
<p>{user.uuid}</p> ////CAN'T GET ANY USERS DATA /////
))}
</div>
))}
</div>
);
}
export default Bus;
Related
I am trying to read data from firebase using nextjs but I get back an empty page. Even when I console log, nothing gets returned. This is how my code looks like
import React, {useState} from 'react'
import { db } from '../firebase'
import { collection, getDocs } from "firebase/firestore";
const reference = collection(db, "students");
function Card(props) {
const { studentsData } = props
return (
<div>
<p>This is just a test</p>
{studentsData && studentsData.map(students => (
<p>{students.name}</p>
))}
</div>
)
}
export const getStaticProps = async () => {
const students = await getDocs(reference);
const studentsData = students.docs.map(doc => ({id: doc.id, ...doc.data() }))
console.log(studentsData);
return {
props: { studentsData }
}
}
export default Card
All I get back from this is just an empty page. Where could I be going wrong?.
I keep getting this error
TypeError: Cannot read property 'useState' of null
whenever I try pulling data from the firestore database. The error points to when I am using the useState and this is how my code looks like
import React from 'react'
import { useState } from 'react';
import { db } from '../firebaseconfig'
import { collection, getDocs } from "firebase/firestore";
const reference = collection(db, "students");
const [students, setstudents] = useState([]);
export const getStaticProps = async () => {
const data = await getDocs(reference);
setstudents(data.docs.map(doc => ({...doc.data(), id: doc.id})));
return {
props: students
}
}
function Card({students}) {
return (
<div>
{students.map(student => (
<h1>{student.name}</h1>
))}
</div>
)
}
export default Card
Where could I be going wrong?
In the code snippet you have provided, the state students does not have any other purpose than being sent as props to Card component.
Based on the nextjs docs (https://nextjs.org/docs/basic-features/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms) , modify the code like this and try
import React from 'react'
import { db } from '../firebaseconfig'
import { collection, getDocs } from "firebase/firestore";
const reference = collection(db, "students");
export const getStaticProps = async () => {
const data = await getDocs(reference);
const students=data.docs.map(doc => ({...doc.data(), id: doc.id}));
return {
props: {
students
}
}
}
function Card({students=[]}) {
return (
<div>
{students.map(student => (
<h1>{student.name}</h1>
))}
</div>
)
}
export default Card
From React Docs there are rules to using Hooks.
React Hooks Rules
Your code should look like this:
function Card({students}) {
const [students, setstudents] = useState([]);
return (
<div>
{students.map(student => (
<h1>{student.name}</h1>
))}
</div>
)
}
This should solve your bug.
Change setstudents to setStudents and I suggest simplify your code:
import React, { useState } from 'react'
import { db } from '../firebaseconfig'
import { collection, getDocs } from "firebase/firestore";
function Card() {
const [students, setStudents] = useState([]);
const fetchStudents=async()=>{
const response=db.collection('students');
const data=await response.get();
setStudents(data.docs.map(doc => ({...doc.data(), id: doc.id}))
);
}
useEffect(() => {
fetchStudents();
}, [])
return (
<div>
{students && students.map(student => (
<h1>{student.name}</h1>
))}
</div>
)
}
export default Card
you are using 2 react imports. Make it one
try this:
import React, { useState} from 'react'
Working on a nextjs app using typescript w/ a firestore backend.
I currently am using my own useContext hook to make globally available a firestore user object, an array of 'business entity IDs' (strings) that the user is authorized to view, as well as an array of objects containing each biz's document data.
Because a user can be a member of multiple business entities, I'd like to be able to have them toggle between a 'current business' object whose document ID would be used to pass into further queries as well as document add / update functions.
I'm just not sure how to go about trigger the setting and switching of this 'current biz' id.
I'm assuming I'd want to somehow set the value in another usecontext hook so that the value is globally available to use around the app?
Below is my current custom context hooks doc
please let me know if you'd need to see any more data
import { auth, firestore } from "../lib/firebase";
import { useContext, useEffect, useState } from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import {
doc,
onSnapshot,
collection,
query,
where,
getDocs,
} from "firebase/firestore";
import { BizContext } from "./context";
//types
// Custom hook to read auth record and user profile doc
export function useUserData() {
const [user, loading, error] = useAuthState(auth);
const [username, setUsername] = useState(null);
useEffect(() => {
// turn off realtime subscription
let unsubscribe;
//this actively listens to a the users collection
if (user) {
const userDocRef = doc(firestore, "users", user.uid);
unsubscribe = onSnapshot(userDocRef, (doc) => {
setUsername(doc.data()?.username);
});
} else {
setUsername(null);
}
return unsubscribe;
}, [user]);
return { user, username };
}
export function useBelongsTo() {
const [user] = useAuthState(auth);
const [belongsTo, setBelongsTo] = useState<[]>([]);
const [bizInfo, setBizInfo] = useState<[]>([]);
useEffect(() => {
let unsubscribe;
if (user) {
const bizColRef = collection(firestore, "businesses");
const q = query(bizColRef, where("admins", "array-contains", user.uid));
unsubscribe = onSnapshot(q, (querySnapshot) => {
let bizId: [] = [];
let bizInfo: [] = [];
querySnapshot.forEach((doc) => {
bizId.push(doc.id);
bizInfo.push(doc.data());
});
setBelongsTo(bizId);
setBizInfo(bizInfo);
});
} else {
setBelongsTo([]);
console.log("no businesses, no user");
}
return unsubscribe;
}, [user]);
return { belongsTo, bizInfo };
}
_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { ChakraProvider } from "#chakra-ui/react";
import customTheme from "../extendTheme";
import { Toaster } from "react-hot-toast";
import { BizContext, UserContext } from "../lib/context";
import { useBelongsTo, useUserData } from "../lib/hooks";
import Layout from "../components/layout/Layout";
function MyApp({ Component, pageProps }: AppProps) {
const userData = useUserData();
const bizData = useBelongsTo();
return (
<ChakraProvider theme={customTheme}>
<UserContext.Provider value={userData}>
<BizContext.Provider value={bizData}>
<Layout>
<Component {...pageProps} />
<Toaster />
</Layout>
</BizContext.Provider>
</UserContext.Provider>
</ChakraProvider>
);
}
export default MyApp;
context.tsx
import React from "react";
export const UserContext = React.createContext({});
export const BizContext = React.createContext({});
If you want to make belongsTo and bizInfo globally for later usage, I recommend you to use react Context instead of using hooks. Move the logic to the context like the sample below.
import { useContext, createContext, useEffect, useState } from "react";
export const AuthContext = createContext();
export function AuthContextProvider({ children }) {
const [user] = useAuthState(auth);
const [belongsTo, setBelongsTo] = useState<[]>([]);
const [bizInfo, setBizInfo] = useState<[]>([]);
const [currentBizId, setCurrentBizId] = useState();
useEffect(() => {
let unsubscribe;
if (user) {
const bizColRef = collection(firestore, "businesses");
const q = query(bizColRef, where("admins", "array-contains", user.uid));
unsubscribe = onSnapshot(q, (querySnapshot) => {
let bizId: [] = [];
let bizInfo: [] = [];
querySnapshot.forEach((doc) => {
bizId.push(doc.id);
bizInfo.push(doc.data());
});
setBelongsTo(bizId);
setBizInfo(bizInfo);
});
} else {
setBelongsTo([]);
console.log("no businesses, no user");
}
return unsubscribe;
}, [user]);
function switchBusinessEntity(id){
let currentBusinessEntity=belongsTo.find(biz=>biz.id === id);
setCurrentBizId(currentBusinessEntity);
}
return <AuthContext.Provider
value={{
belongsTo,
bizInfo,
currentBizId,
switchBusinessEntity
}}>
{children}
</AuthContext.Provider>;
}
export const useAuthContext = () => useContext(AuthContext);
And in the _app.js, wrapper the App with AuthContextProvider
import { AuthContextProvider } from "#/contexts/authContext";
function MyApp({ Component, pageProps }) {
return <AuthContextProvider>
<Component {...pageProps} />
</AuthContextProvider>;
}
export default MyApp;
And in the component, you can access the global states like this:
function YourComponent(){
const {
belongsTo,
bizInfo,
currentBizId,
switchBusinessEntity
} = useAuthContext()
return <select onChange={e => switchBusinessEntity(e.target.value)>
{belongsTo.map((bizId, index) => <option key={index} value={bizId.value}>{bizId}</option>)}
</select>
}
I'm taking the React course at coderhouse and we're taking Firebase's Firestore database; We are setting up a virtual store and we have to bring the articles from the database, I have the following problem when I want to bring the articles of a category it brings it to me but when I want them to load everything, what would it be in the index the page does not load.
Can you tell me why? Thank you. I leave you my code and the error it is giving me, how do I solve it, thank you.
React-dom.development.js:22738 Uncaught FirebaseError: Function where() called with invalid data. Unsupported field value: undefined
import React, {useEffect, useState} from "react";
import '../App.css';
import 'materialize-css/dist/css/materialize.css';
import ItemList from './ItemList';
import CircularProgress from '#mui/material/CircularProgress';
import { useParams } from "react-router-dom";
import { db } from '../firebase/firebase';
import { getDocs, collection, query, where, getDoc } from "firebase/firestore";
export const ItemListContainer =() => {
const [swSell,setSwSell] = useState([])
const [cargar,setCargar] = useState(true)
const {categoryID} = useParams();
useEffect(() => {
const productCollection = collection(db, 'Products');
const productQuery = query(productCollection, where('category', '==', categoryID));
const URL= categoryID == null ? productQuery : productCollection;
console.log(URL)
getDocs(URL)
.then(result => {
const lista = result.docs.map(element => {
return {
...element.data(),
}
})
setSwSell(lista);
})
.catch(error => console.err)
.finally(() => setCargar(false));
/* const URL = categoryID
return(
<>
{
<main className="items">
<div className="parent" key={swSell.id}>
{cargar ? <CircularProgress color="primary"/>:<ItemList product={swSell} />}
</div>
</main>
}
</>
);
}
export default ItemListContainer;
You should run the query when categoryID is not null. Hence your ternary operator should be opposite.
const URL = categoryID === null ? productCollection : productQuery;
I have this problem, can anyone help me?
TypeError: customers.map is not a function.
I've always used it that way and I've never had any problems.
Its about data integration.
Basically is that, please anyone can help me?
import React, { useState, useEffect } from "react";
import { List, Card } from "antd";
import { data } from "../../../mocks/customers";
import { DeleteCustomerButton } from "#components/atoms/DeleteCustomerButton";
import { CustomersEditButton } from "#components/atoms/CustomersEditButton";
import { useContext } from "../../../contexts/context";
const { Meta } = Card;
const CustomersCardList: React.FC = () => {
const customers: any = useContext();
return (
<div>
{customers.map((customer, key) => { })}</div>)
}
//context.tsx
import * as React from 'react';
import axios from 'axios';
export const AccountContext = React.createContext({});
export const useContext = () => React.useContext(AccountContext);
interface AccounterContextProviderProps {
value: any
};
export const AccounterContextProvider: React.FC<AccounterContextProviderProps> = ({ children, value }) => {
const [customers, setCustomers] = React.useState<any>([]);
React.useEffect(() => {
const getCustomers = async () => {
const result = await axios.get("http://localhost:3333/customers");
setCustomers(result.data);
}
getCustomers();
}, []);
console.log(customers);
return (
<AccountContext.Provider value={{ ...value, customers }}>
{children}
</AccountContext.Provider>
)
};
Any can be anything not only array, so it will not have a map method. Use const customers:any[] = useContext() instead