ReferenceError: Cannot access 'db' before initialization - database

Getting an error cannot access 'db' before initialization. Not sure what is wrong here.
db is defined and imports from firebase.js to posts.js
Please help.
----firebase.js----
[// Initialize Firebase
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
const db = getFirestore();
const storage [enter image description here][1]= getStorage();
export { app, db, storage };][1]
----posts.js----
import Post from "./Post";
import { collection, onSnapshot, orderBy, query } from "firebase/firestore";
import { db } from "../firebase";
import { useEffect, useState } from "react";
function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
const unsubcribe = onSnapshot(
query(collection(db, "posts"), orderBy("timestamp", "desc")),
(snapshot) => {
setPosts(snapshot.docs);
}
);
return () => {
unsubcribe();
};
}, [db]);
return (
<div>
{posts.map((post) => (
<Post
key={post.id}
id={post.id}
username={post.data().username}
userImg={post.data().profileImg}
img={post.data().image}
caption={post.data().caption}
/>
))}
</div>
);
}
export default Posts;

Related

no rendered data from endpoint reactjs

I am building a project using Reactjs and ready endpoints to render the data from it.
I have been following this video tutorial
it was working fine until I got to render the data to the browser not only in the console
what am I doing wrong?
import {React, useEffect, useState} from 'react';
import axios from 'axios';
function App() {
const [isLoading, setIsLoading] = useState(true);
const [posts, setPosts] = useState({});
useEffect(() => {
getData();
}, []);
const getData = () => {
const ENDPOINT= "https://snetmyapp.herokuapp.com/case1";
axios (ENDPOINT)
.then((response: any) => {
setIsLoading(false);
console.log("RES",response.data);
if (response.data.posts) {
setPosts(response.data.posts)
}
else
console.log("No posts");
});
};
const data = isLoading ? (
<p>Loading...</p>
) : (
<div><pre>{JSON.stringify(posts, null, 2)}</pre></div>
);
return (
<div>{data}</div>
);
}
export default App;
It looks like there are no posts in returned data
offerList is returned instead.
Check out this sandbox

Weird React Native Behavior

I have been building this mobile app with React Native/Expo and Firestore for a while now. The app schedules study sessions, and when a study session is active, a Pomodoro timer screen is to be shown, and when a session is inactive, the main homepage should be shown. However, I have been having trouble implementing this after a refactor to my database structure. Currently, for each schedule, a document is created in a subcollection corresponding to the user's UID. So, the path for a schedule would be "Users/(auth.currentUser.uid)/S-(auth.currentUser.uid)/(document id). To implement this feature, I have tried to run a function every second that checks through all of the documents and finds out whether a schedule is active, and if it is, it shows the Pomodoro timer screen. However, there is some weird behavior occurring. I am reading the database once using a Context Api, and the data shows perfectly in the screen where you view all your schedules, however in the function it is showing as an empty object. I have a feeling that it might be due to the bounds of the Context, however I am not sure. Does anyone know why?
CurrentDataProvider.js
import React, { createContext, useEffect, useState } from "react";
import {
doc,
getDocs,
onSnapshot,
collection,
query,
} from "firebase/firestore";
import { db, auth } from "../config/firebase";
export const CurrentDataContext = createContext({});
const CurrentDataProvider = ({ children }) => {
const [data, setData] = useState({});
useEffect(async () => {
if (auth.currentUser) {
const ref = query(
collection(
db,
"Users",
auth.currentUser.uid,
`S-${auth.currentUser.uid}`
)
);
const unsub = onSnapshot(ref, (querySnap) => {
let dat = {};
querySnap.forEach((doc) => {
dat[doc.id] = doc.data();
});
setData(dat);
});
return () => unsub;
}
}, []);
return (
<CurrentDataContext.Provider value={{ data, setData }}>
{children}
</CurrentDataContext.Provider>
);
};
export { CurrentDataProvider };
function being used to read schedules
const readSchedules = () => {
const currentTime = new Date();
Object.keys(data).forEach((key) => {
const clientSeconds =
currentTime.getHours() * 3600 + currentTime.getMinutes() * 60;
const startTimestamp = new Timestamp(data[key]["start"]["seconds"]);
const endTimestamp = new Timestamp(data[key]["end"].seconds);
const utcStartSeconds = startTimestamp.seconds;
const utcEndseconds = endTimestamp.seconds;
console.log(utcStartSeconds, clientSeconds, utcEndseconds);
const greaterTime = clientSeconds > utcStartSeconds;
const lessTime = clientSeconds < utcEndseconds;
const trueDay = data[key][dayOfWeekAsString(currentTime.getDay())];
if (trueDay) {
if (greaterTime && lessTime) {
setPomodoro(true);
setCurrentSchedule(key.toString());
console.log(`Schedule ${currentSchedule} selected!`);
return;
}
}
});
setPomodoro(false);
};
RootStack.js
import SplashScreen from "../screens/SplashScreen";
import AuthStack from "./AuthStack";
import React, { useState, useContext, useEffect } from "react";
import { View, ActivityIndicator } from "react-native";
import { auth } from "../config/firebase";
import { onAuthStateChanged } from "firebase/auth";
import { UserContext } from "./../components/UserProvider";
import { NavigationContainer } from "#react-navigation/native";
import FinalStack from "./MainStack";
import { CurrentDataProvider } from "../components/CurrentDataProvider";
const RootStack = () => {
const { user, setUser } = useContext(UserContext);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const authListener = auth.onAuthStateChanged(async (user) => {
try {
await (user ? setUser(user) : setUser(null));
setTimeout(() => {
setIsLoading(false);
}, 3000);
} catch (err) {
console.log(err);
}
});
return authListener;
}, []);
if (isLoading) {
return <SplashScreen />;
}
return (
<NavigationContainer>
{user ? (
<CurrentDataProvider>
<FinalStack />
</CurrentDataProvider>
) : (
<AuthStack />
)}
</NavigationContainer>
);
};
export default RootStack;
Thanks for all your help!

how use get method in react js

this is my react code here I fetch the data from the backend using mongo. my data is appearing in the console but not appearing on the web page it's showing `users.map is not a function. but if I try the jsonplaeholder API then its work properly.
import React, { useEffect, useState } from "react";
const Get = () => {
const [users,setUsers] = useState([]);
const getAllUser = async () => {
const response = await fetch("/get");
setUsers(await response.json());
console.log(users);
};
useEffect(() => {
getAllUser();
},[]);
return (
<>
{ users.map((ce) =>
<div key={ce.id}>
<h2>{ce.name}</h2>
<p>{ce.email}</p>
</div>)}
</>
)
}
export default Get;
this is the db data
{"status":"success","results":2,"data":{"users":[{"_id":"6134fcc6eddae0ec522fecd7","name":"ram ","email":"ram#gmail.com","number":9455294552,"__v":0},{"_id":"61364d918a8ab07512094443","name":"rawal","email":"rawal#gmail.com","number":9309304400,"__v":0}]}}
You need to properly set your state with res.data.users as follows.
import React, { useEffect, useState } from "react";
const Get = () => {
const [users, setUsers] = useState([]);
const getAllUser = async () => {
const response = await fetch("/get");
response.json().then((res) => setUsers(res.data.users));
console.log(users);
};
useEffect(() => {
getAllUser();
}, []);
return (
<>
{users.map((ce) => (
<div key={ce.id}>
<h2>{ce.name}</h2>
<p>{ce.email}</p>
</div>
))}
</>
);
};
export default Get;

React App crashes when fetching searchresults from django API

My React App is crashing when fetching searchResults from API, I have checked the API urls wise search queries and it works perfectly however when i try to send input via React and display results it crashes and even freezes my PC. I dont understand whats going on here. I have fetched results from the API in React without search query and it works. So the API works when used via Curl and React app can fetch and display all the data but unable to display specific data. Below is my code:
function Search() {
const [data, setData] = React.useState([]);
const [searchTerm, setSearchTerm] = React.useState("");
const handleChange = e => {
setSearchTerm(e.target.value);
};
React.useEffect(() => {
if (searchTerm) {
getData(searchTerm);
}
});
const getData = (searchTerm) => {
axios.get("http://localhost:8000/SearchPost/?search="+searchTerm)
.then(res => (setData(res.data)))
}
return (
<div className="App">
<input
type="text"
placeholder="Search"
value={searchTerm}
onChange={handleChange}
/>
<ul>
{data.map(item => (
<li>{item.co_N}</li>
))}
</ul>
</div>
);
}
export default Search;
One solution is to "debounce" setting searchTerm to minimize the request to the API:
we're going to use lodash package particularly it's debounce method (doc here), and useCallback from Hooks API (doc here) :
import React, { useState, useCallback, useRef } from "react";
import _ from "lodash";
import axios from "axios";
import TextField from "#material-ui/core/TextField";
const SearchInputComponent = ({ label }) => {
const [value, setValue] = useState("");
const [data, setData] = useState([]);
const inputRef = useRef(null);
const debounceLoadData = useCallback(
_.debounce((value) => {
getData(value);
}, 500), // you can set a higher value if you want
[]
);
const getData = (name) => {
axios.get(`https://restcountries.eu/rest/v2/name/${name}`).then((res) => {
console.log(res);
setData(res.data);
});
};
const handleSearchFieldChange = (event) => {
const { value } = event.target;
setValue(value);
debounceLoadData(value);
};
return (
<>
<TextField
inputRef={inputRef}
id="searchField"
value={value}
label={"search"}
onChange={handleSearchFieldChange}
/>
{data &&
<ul>
{data.map(country=> (
<li key={country.alpha3Code}>{country.name}</li>
))
}
</ul>
}
</>
);
};
export default SearchInputComponent;
with this code the front end will wait 500 ms before fetching api with the search input value.
here a sandBox example.
Possible Feature: Make search field generic
If in the future you will need a search component you can make it generic with Context:
first create a context file named for example SearchInputContext.js and add:
SearchInputContext.js
import React, {
createContext,
useState
} from 'react';
export const SearchInputContext = createContext({});
export const SearchInputContextProvider = ({ children }) => {
const [value, setValue] = useState('');
return (
<SearchInputContext.Provider
value={{ searchValue: value, setSearchValue: setValue }}
>
{children}
</SearchInputContext.Provider>
);
};
Next create a generic searchField component named for example SearchInput.js and add in it :
SearchInput.js
import React, {
useState,
useCallback,
useRef,
useContext
} from 'react';
import _ from 'lodash';
import TextField from "#material-ui/core/TextField";
import { SearchInputContext } from './SearchInputContext';
const SearchInputComponent = () => {
const [value, setValue] = useState('');
const { setSearchValue } = useContext(SearchInputContext);
const inputRef = useRef(null);
const debounceLoadData = useCallback(
_.debounce((value) => {
setSearchValue(value);
}, 500),
[]
);
const handleSearchFieldChange = (event) => {
const { value } = event.target;
setValue(value);
debounceLoadData(value);
};
return (
<>
<TextField
inputRef={inputRef}
id="searchField"
value={value}
label={"search"}
onChange={handleSearchFieldChange}
/>
</>
);
};
export default SearchInputComponent;
After in your App.js (or other component page where you want a searchField) add your ContextProvider like this:
App.js
import {ListPage} from "./searchPage";
import {SearchInputContextProvider} from './SearchInputContext';
import "./styles.css";
export default function App() {
return (
<SearchInputContextProvider>
<ListPage/>
</SearchInputContextProvider>
);
}
And finally add your searchComponent where you need a search feature like in the ListPage component :
SearchPage.js:
import React, { useState,useContext, useEffect } from "react";
import axios from "axios";
import SearchInputComponent from './SearchInput';
import {SearchInputContext} from './SearchInputContext'
export const ListPage = () => {
const [data, setData] = useState([]);
const { searchValue } = useContext(SearchInputContext);
useEffect(() => {
if(searchValue){
const getData = (name) => {
axios.get(`https://restcountries.eu/rest/v2/name/${name}`).then((res) => {
console.log(res);
setData(res.data);
});
};
return getData(searchValue)
}
}, [ searchValue]);
return (
<>
<SearchInputComponent />
{data &&
<ul>
{data.map(country=> (
<li key={country.alpha3Code}>{country.name}</li>
))
}
</ul>
}
</>
);
};
here a sandbox link of this example

axios in react works locally but doesn't work in heroku

I used axios twice. onces on internal api in my express server, and once external api in react. Getting internal api from express to react works, but getting external api in react is not working
It does work locally but it's doing nothing when deployed in heroku
Below code is where getting api data doesn't work. Also I can't find any record of getting the data when I check the log in heroku
import React, { useState, useEffect } from "react";
import Axios from "axios";
export default function Weather() {
const [weather, setWeather] = useState("");
const [currentWeather, setCurrentWeather] = useState("");
const [feelsLike, setFeelsLiks] = useState("");
const [tempMax, setTempMax] = useState("");
const [tempMin, setTempMin] = useState("");
useEffect(() => {
Axios.get(
"http://api.openweathermap.org/data/2.5/weather?q=Seoul&appid=4a80048ac273c6f7e70908e2bb631fee"
).then((response) => {
setWeather(response.data.weather[0].main);
setCurrentWeather(Math.floor(response.data.main.temp - 273));
setFeelsLiks(Math.floor(response.data.main.feels_like - 273));
setTempMax(Math.floor(response.data.main.temp_max - 273));
setTempMin(Math.floor(response.data.main.temp_min - 273));
});
});
return (
<div>
<h3>Weather</h3>
<div id="displayWeather">
<p>{weather}</p>
<p>temp: {currentWeather}°</p>
<p>feels like: {feelsLike}°</p>
<p>Max temp: {tempMax}°</p>
<p>Min temp: {tempMin}°</p>
</div>
</div>
);
}
and below is where getting data works
import React, { useState, useEffect } from "react";
import Axios from "axios";
export default function News() {
const [recentNews, setRecentNews] = useState([]);
const [newsUrl, setNewsUrl] = useState([]);
useEffect(() => {
Axios.get("api/newsname").then((response) => {
setRecentNews(response.data);
});
Axios.get("/api/newsurl").then((response) => {
setNewsUrl(response.data);
});
});
const data = [];
for (let i = 0; i < recentNews.length; i++) {
data.push(<a href={newsUrl[i]}>{recentNews[i]}</a>);
}
return (
<div>
<h3>News</h3>
<div id="displayNews">
{data.map((element) => {
return <li className="list">{element}</li>;
})}
</div>
</div>
);
}

Resources