How to fetch and display data from documents in subcollection in react - reactjs

I want to display data from firestore in the simplest way because I'm a beginner in react. Here is the tree of my data of firestore.
collection-[ documentsList [ subcolletcion [ documentsList [ data

To fetch data you can do it like this:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
const getData = async () => {
const result = await axios('https://route_to_backend.com/bla-bla');
setData(result.data);
}
getData();
}, []);
return (
<ul>
{data && data.map(item => (
<li key={item.id}>
<div>{item.title}</div>
</li>
))}
</ul>
);
}
export default App;
If you provide some example of objects that you receive from server I can write code how you can render it.

Related

React JS. Trying to display data from a local JSON file

I am quite new in learning React and now I am trying to implement some dynamic filters on a locat data set and I am stuck at displaying data from my local file.
Data entries look like this:
I was trying to use the fetch() API but for some reason the data is not displayed on the page. Most probably I am not reffering correct to the right attributes.
`
import data from '../file2.json'
import React, { useEffect, useState } from "react";
const Planner = () => {
const [user, setUser] = useState([]);
const fetchData = () => {
return fetch(data)
.then((response) => response.json())
.then((data) => setUser(data));
}
useEffect(() => {
fetchData();
},[])
return (<main>
<h1>Restaurant List</h1>
<ul>
{user && user.length > 0 && user.map((userObj, index) => (
<li key={userObj.restaurant.R.res_id}>{userObj.name}</li>
))}
</ul>
</main>
)
};
export default Planner;`

React hook "useMemo" with array as dependency

I am new to react (that I use with typeScript) and I am facing an issue with the use of the useMemo hook.
Here is my fetching service:
export default class FetchingService {
datas: Data[] = [];
constructor() {
this.fetch();
}
async fetch(): Promise<Data[]> {
const d = // await an async array from an api, using Array.flat()
this.datas = d;
console.log(this.datas);
return d;
}
}
In a component, I try to watch for change of the datas attribute of my service:
import fetchingService from '../services/fetchingService.ts';
const Home: React.FC = () => {
const ds: Data[];
const [datas, setDatas] = useState(ds);
const fetchDatas = useMemo(() => {
console.log('Render datas', fetchingService.datas?.length)
setDatas(fetchingService.datas);
return fetchingService.datas;
}, [fetchingService.datas]);
return (
<ul>{datas.map(d => {
return (
<li key={d.id}>{d.id}</li>
);
</ul>
);
}
The problem I am facing is that the useMemo hook is not recompouted when the datas attribute changes within my fetchService. I am pretty sure that my FetchingService.fetch() function works because the console.log within the fetch function always display the fetched datas.
The observed behavior is that sometimes datas are well rendered (when fetch ends before rendering ...), but sometimes it isn't.
The expected one is that datas are rendered every time and only on refresh, exept when datas are modified
I also tried to put the length of the data array as a dependency in useMemo, but in both cases it doesn't work and I have a warning in my IDE, telling me it is an unnecessary dependency.
I don't really understand if it is a typescript or a specific react behavior issue. I think the reference of the datas attribute should change at the end of the fetch (or at least its length attribute ...), but tell me if I am wrong.
I do appreciate every help !
in fetchingService, when datas change, probably the dependency cannot be accepted. You can use a custom hook in stead of it.
You can use this source about useMemo: useMemo with an array dependency?
import { useState, useLayoutEffect, useCallback } from "react";
export const useFetchingService = () => {
const [fetchedData, setFetchedData] = useState([]);
const fetch = useCallback(async () => {
const d = await new Promise((res, rej) => {
setTimeout(() => {
res([1, 2, 3]);
}, 5000);
}); // await an async array from an api, using Array.flat()
setFetchedData(d);
}, []);
useLayoutEffect(() => {
fetch();
}, []);
return [fetchedData];
};
useLayoutEffect runs before rendering
using:
const [fetchData] = useFetchingService();
const fetchDatas = useMemo(async () => {
console.log("Render datas", fetchData.length);
setDatas(fetchData);
return fetchData;
}, [fetchData]);
You can also use this directly without 'datas' state.
I hope that this will be solution for you.
So I put together a codesandbox project that uses a context to store the value:
App.tsx
import React, { useState, useEffect, createContext } from "react";
import Home from "./Home";
export const DataContext = createContext({});
export default function App(props) {
const [data, setData] = useState([]);
useEffect(() => {
const get = async () => {
const d = await fetch("https://dummyjson.com/products");
const json = await d.json();
const products = json.products;
console.log(data.slice(0, 3));
setData(products);
return products;
};
get();
}, []);
return (
<div>
Some stuff here
<DataContext.Provider value={{ data, setData }}>
<Home />
</DataContext.Provider>
</div>
);
}
Home.tsx
import React, { FC, useMemo, useState, useEffect, useContext } from "react";
import { DataContext } from "./App";
import { Data, ContextDataType } from "./types";
const Home: FC = () => {
const { data, setData }: ContextDataType = useContext(DataContext);
return (
<>
<ul>
{data.map((d) => {
return (
<li key={d.id}>
{d.title}
<img
src={d.images[0]}
width="100"
height="100"
alt={d.description}
/>
</li>
);
})}
</ul>
</>
);
};
export default Home;
This was my first time using both codesandbox and typescript so I apologize for any mistakes

Getting data with axios but unable to display with html

I am trying to display a list of towns or departments from an API, I can display the data with console.log but when i put it in html its not working.
here's my ListTown.js:
import React, { useEffect, useState } from "react";
import api from "./api";
function ListTowns() {
const DEPARTEMENTS = "/get/location/departements";
const [departements, setDepartements] = useState([]);
useEffect(() => {
const fetchData = async () => {
const response = await api.get(DEPARTEMENTS).then((response) => {
setDepartements(response.data.data.departements);
});
};
fetchData();
}, []);
return (
<div>
<ul>
{departements.map((dep) => {
<li key={dep.id}>{dep.name}</li>;
})}
</ul>
</div>
);
}
export default ListTowns;
console log (dep.name) gives this result console.log(dep.name)
You forgot to return the data out of your .map method, so right now it's returning undefined for each element.
{departements.map((dep) => {
return <li key={dep.id}>{dep.name}</li>;
})}

TypeError: X.map is not a function (fetching api into an object not into an array)

new to Reactjs!
I fetch an api (using axios) and then try to map thought it but i cannot because its an object.
How can i fix this! how can i get specific data of that object ?
I wanna fetch the names of the memes.
if i use another API like this one ex." https://www.breakingbadapi.com/api/" and use an extra path ( / ) in html like this
ex. https://www.breakingbadapi.com/api/**characters** i get an array and i get the job done.
Why the same ex. as above doesnt work with my case?
!The Error that i get is memes.map is not a function!
Here is my code:
import React, { useState, useEffect } from "react";
import axios from "axios";
import { Header } from "./components/Header";
import Memes from "./components/Memes";
import "./App.css";
const App = () => {
const [memes, setMemes] = useState({});
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchItems = async () => {
const result = await axios("https://api.imgflip.com/get_memes");
console.log(result.data);
setMemes(result.data);
setIsLoading(false);
};
fetchItems();
}, {});
return (
<div className="App">
<Header />
<Memes isLoading={isLoading} memes={memes} />
</div>
);
};
export default App;
import React from "react";
const Memes = ({ isLoading, memes }) => {
return isLoading ? (
<h1>Loading</h1>
) : (
<section>
{memes.map((meme) => (
<h1 key={meme.char_id}>{meme.name}</h1>
))}
</section>
);
};
export default Memes;
wrong code : const [memes, setMemes] = useState({});
update code :const [memes, setMemes] = useState([]);
On First render memes value will be null ( sync code rendering ). Please try the following
{memes?.map((meme) => (
<h1 key={meme.char_id}>{meme.name}</h1>
))}
? will make sure to run map once the meme array is populated with data.
Also, useState should have [] as init value like:
const [meme, setMeme] = useState([])

I receive "TypeError: items is undefined" when trying to map items from a JSON

I am currently trying to setup a React web app using React hooks. I try to pull the items from the JSON with Map but I receive this error.
TypeError: items is undefined
Shop.js
import React, {useState, useEffect} from 'react';
import './App.css';
function Shop() {
useEffect(() => {
fetchItems();
}, []);
const [items, setItems] = useState([]);
const fetchItems = async () => {
const data = await fetch('https://fortnite-api.theapinetwork.com/upcoming/get');
const items = await data.json();
console.log(items.items);
setItems(items.items);
};
return (
<div>
{items.map(item => (
<h1>{item.map}</h1>
))}
</div>
);
}
export default Shop;
I'm not an expert on React, but I'm pretty sure its because you get to the return statement before you define items.
That function is async, so while it takes its turn running each line, the program itself will move on, thus getting to the return with "items" in it before items is actually defined.
What might fix it is doing an if/else that checks if items is defined, then returns either blank html or the html with items. React dynamically updates so that should then return the correct html once items is loaded.
This should solve your question. I have checked the response from the GET request you provided and you have used the incorrect data structuring when pulling fields out. Try the code below.
import React, {useState, useEffect} from 'react';
import './App.css';
function Shop() {
useEffect(() => {
fetchItems();
}, []);
const [items, setItems] = useState([]);
const fetchItems = async () => {
const response = await fetch('https://fortnite-api.theapinetwork.com/upcoming/get');
const deserialisedResponse = await response.json();
setItems(deserialisedResponse.data);
};
return (
<div>
{items.map((item, index) => (
<h1 key={index}>{item.map}</h1>
))}
</div>
);
}
export default Shop;
I've tried on my end and confirmed it works.
Let me show the codes.
function Shop() {
useEffect(() => {
fetchItems();
}, []);
const [items, setItems] = useState([]);
const fetchItems = async () => {
const response = await fetch('https://fortnite-api.theapinetwork.com/upcoming/get');
const deserialisedResponse = await response.json();
console.log("result: ", deserialisedResponse)
setItems(deserialisedResponse.data);
};
return (
<div>
{items.map((item, idx) => (
<h1 key={idx}>{item.item.name}</h1>
))}
</div>
)
}
Please have a check and let me know if it works or not.

Resources