How to clone a collection and transform it into one file? - reactjs

I have structure collections
users
|_DC
|_OfertDC
|_{documentID}
|_SC
|_OfertaSC
|_{documentID}
|
|_{documentID}
I want to create clone, marge of this structure in this way
const data = [
...{documentID}
ofertaSD: OfertaSC/{documentID},
ofertaDC: OfertaDC/{documentID}]
all documentsID have {userID} and this is way I want
My idea is to display it on front-end with no possibility to write; just one time in day my next's app would fetch the date.
const [user, loading, error] = useAuthState(auth);
const URC = collection(db, "Users")
const [dataUsers, setDataUsers] = useState([])
const [ofertyDC, setOfertyDC] = useState([])
useEffect(() => {
const getUsers = async (users) => {
const data = await getDocs(URC)
setDataUsers(data.docs.map((doc) => ({...doc.data(), id: doc.id})))
}
const getDC = async (users) => {
const ofertasDC = query(collectionGroup(db, 'OfertaDC'));
const data = await getDocs(ofertasDC)
data.forEach(doc =>{
const datas = data.docs.map((doc) => ({...doc.data(), id: doc.id}))
setOfertyDC(datas[0].modulyPV)
})}
getUsers();
getDC();
},[])
const [complexDatas, setComplexDatas] = useState([])
useEffect(() => {
var i;
const complexData = []
for(i=0; i = dataUsers.length; i++) {
if(dataUsers.uid === ofertyDC.uid){
complexData.push({...dataUsers[i],
ofertaDC: ofertyDC[i]})
}}
console.log("complexData", complexData)
}, [dataUsers, setDataUsers, ofertyDC, setOfertyDC])
I do not know where is an error. I can load the page but no move and, there is no any error on a console.

Related

Array pushes elements already in Array despite !arry.includes

I am trying to build an app that requires a directory. Every time I update the component, it pushes the data into the array again creating multiple copies. I tried solving that by adding an !arry.includes, but that does not stop it for adding another occurrence of the data.
const Directory = () => {
const [searchResults, setSearchResults] = useState([]);
const [loading, setLoading] = useState(false);
const { currentUser } = useContext(AuthContext);
useEffect(() => {
setLoading(true);
const data = async () => {
const q = query(collection(db, "users"), where("type", "==", "doctor"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
const data = doc.data();
if (!searchResults.includes(data)) {
searchResults.push(data);
}
});
setLoading(false);
};
data();
},[]);
console.log(searchResults);
It appears that you are trying to compare objects here which doesn't work with the array.includes() method.
In javascript
const user1 = {name : "nerd", org: "dev"};
const user2 = {name : "nerd", org: "dev"};
user1 == user2; // is false
You would need to search for something more specific or try Comparing Objects. Either way what your trying to do is tricky and you may need to explore lodash or something to solve it
I found an easier way!
useEffect(() => {
setLoading(true);
const data = async () => {
const q = query(collection(db, "users"), where("type", "==", "doctor"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
const data = doc.data();
const notInArray = searchResults.some(u => u.uid === data.uid);
console.log(notInArray);
if (notInArray === false) {
searchResults.push(data)
}
});
setLoading(false);
};
return () => {
data();
};
}, []);

Fetch data from firebase and initialise it in the useState before its mounted

I am a beginner in react trying to fetch an object from firebase and I would like to initialise the useState with the data fetched from the database,but each time the data renders undefined value.Here is my truncated code
const ProductDetails = () => {
const [tab, setTab] = useState("desc");
const [products, setProducts] = useState([]);
const reviewUser = useRef("");
const reviewMsg = useRef("");
const dispatch = useDispatch();
const [rating, setRating] = useState(null);
const { id } = useParams();
const product = products.find(
async (item) => (await item.key.slice(1)) === id
);
const {
image: imgUrl,
title: productName,
amount: price,
description,
shortDesc,
category,
} = product.data;
const fetchProducts = async () => {
const db = getDatabase();
const thumbnailRef = ref(db, "Contents/");
onValue(thumbnailRef, (snapshot) => {
snapshot.forEach((childSnapshot) => {
const childData = childSnapshot.val();
const childKey = childSnapshot.key;
setProducts((prev) => [...prev, { key: childKey, data: childData }]);
});
});
};
useEffect(() => {
fetchProducts();
}, []);
the error I get is "cannot read properties of undefined (reading 'data')".As I said I am a beginner to react and it could be I am making an amateur mistake,
First, you don't have to use async/ await inside the find. Also wrap it around useMemo to execute only when products change.
const product = useMemo(() => products.find(
(item) => item.key === id
), [products]);
secondly, product value could be ended up with undefined values. so needs to handle that.
const {
image: imgUrl,
title: productName,
amount: price,
description,
shortDesc,
category,
} = product?.data || { image: '',title: '',amount: '',description: '',shortDesc: '',category: '',};
There should not be async await in product function

Map data on runtime after post request

I have three apis in all. GetAssets is the first, followed by assetsOptionsList and getAssetsLibrary. The issue I'm having is that when I post the data on getAssetsLibrary, I want to be able to present it on get Assets at runtime.Everything is working fine but i want to show assets on runtime.
I'm setting the runTime state true on get request but the problem is it works only for one time.Second time, it does not map on runtime. Actually, i want to know is there any alternative so that i can achieve the goal.
In the below code the one function is getting the assets. And i want to run the one function when the post request successfully sent.
const [images, setImages] = useState([]);
const [assetOptions, setAssetOptions] = useState([]);
const [faqOpened, setToggleFaq] = useState(false);
const [runTime, setRunTime] = useState(false)
const [assetID, setAssetID] = useState()
const [isLoading, setIsLoading] = useState(false);
const handleForm = (e) => {
const index = e.target.selectedIndex;
const el = e.target.childNodes[index]
const option = el.getAttribute('id');
setAssetID(option)
}
const formHandler = (e) => {
e.preventDefault()
let formData = new FormData();
formData.append('media', e.target.media.files[0]);
formData.append('assetListId', assetID)
formData.append('name', e.target.name.value);
console.log(Object.fromEntries(formData))
const res = axios.post('api/asset-library',
formData
).then((response) => {
showSuccessToaster(response?.data?.message)
setRunTime(true)
setToggleFaq(false)
})
.catch((error) => {
showErrorToaster(error?.response?.data?.message)
})
}
const showSuccessToaster = (response) => {
return uploadToasterSuccess.show({ message: response });
}
const showErrorToaster = (error) => {
return uploadToasterError.show({ message: error });
}
const one = async () => {
setIsLoading(true)
const data = await axios.get('api/assets').then((res) => {
return res?.data?.data
})
setImages(data)
setIsLoading(false)
}
const two = async () => {
const data = await axios.get('/api/asset-list').then((res) => {
return res?.data?.data
})
setAssetOptions(data)
}
useEffect(() => {
one()
two()
}, [runTime]);

Can i fetch multiple API and set states between api calls? (React and axios)

I want to fetch api and set state, then fetch another api with the state that comes from first one. So is that possible ?
Here is my code that i struggle with ;
useEffect(()=>{
const fetchPokemonSpecies = async (pokemon) => {
const data = await axios("https://pokeapi.co/api/v2/pokemon-species/"+pokeName).then( (response) =>
axios(response.data.evolution_chain.url)).then((response) => {setPokemonFirstEvolution(response.data.chain.evolves_to[0].species.name)
setPokemonFirstForm(response.data.chain.species.name)
setPokemonSecondEvolution(response.data.chain.evolves_to[0].evolves_to[0].species.name)})
setPokemonSpecies(data)
setPokemonCategory(data.genera[7].genus)
}
Thanks already !
So i just solve my problem this way ;
const [pokemonCategory, setPokemonCategory] = useState([])
const [pokemonSecondEvolution, setPokemonSecondEvolution] = useState([])
const [pokemonFirstEvolution, setPokemonFirstEvolution] = useState([])
const [pokemonFirstForm, setPokemonFirstForm] = useState([])
const [pokemonFirstFormIcon, setPokemonFirstFormIcon] = useState([])
const [pokemonFirstEvoIcon, setPokemonFirstEvoIcon] = useState([])
const [pokemonSecondEvoIcon, setPokemonSecondFormIcon] = useState([])
useEffect(()=>{
const fetchPokemonSpecies = async (pokemon) => {
const data = await axios("https://pokeapi.co/api/v2/pokemon-species/"+pokeName).then( (response) => response.data)
setPokemonSpecies(data)
setPokemonCategory(data.genera[7].genus)
const data2 = await axios(data.evolution_chain.url).then((response) => axios("https://pokeapi.co/api/v2/pokemon/"+response.data.chain.evolves_to[0].species.name))
setPokemonFirstEvoIcon(data2.data.sprites.other.dream_world.front_default)
const data3 = await axios(data.evolution_chain.url).then((response) => axios("https://pokeapi.co/api/v2/pokemon/"+response.data.chain.evolves_to[0].evolves_to[0].species.name))
setPokemonSecondFormIcon(data3.data.sprites.other.dream_world.front_default)
const data4 = await axios(data.evolution_chain.url).then((response) => axios("https://pokeapi.co/api/v2/pokemon/"+response.data.chain.species.name))
setPokemonFirstFormIcon(data4.data.sprites.other.dream_world.front_default)
}
fetchPokemonSpecies()
},[])
useEffect(()=>{
const fetchPokemonEvoChain = async (pokemon) => {
const data = await axios("https://pokeapi.co/api/v2/pokemon-species/"+pokeName).then( (response) =>
axios(response.data.evolution_chain.url)).then((response) => {setPokemonFirstEvolution(response.data.chain.evolves_to[0].species.name)
setPokemonFirstForm(response.data.chain.species.name)
setPokemonSecondEvolution(response.data.chain.evolves_to[0].evolves_to[0].species.name)})
}
fetchPokemonEvoChain()
},[])
idk if it is the optimal way but it works

React Firebase data is undefined

I'm trying to build a fintech website, and I have a users collection and a transactions collection. One user can send money to another user by using their phone number.
The user schema contains these
uid - string
phone - string
.....//other data
I need to achieve the following functionality
Enter phone number of target receiver
Get details of user with the entered phone number
Add this data to another collection called transactions
I tried doing that, but I'm getting a bug that in the 3rd step, the data from the 2nd step is undefined. Here's my code
const SendMoney = () => {
const [receiverDetails, setRecieverDetails] = useState({})
const [allUsers, setAllUsers] = useState([])
const [receiverphone, setReceiverphone] = useState('')
const usersCollectionRef = collection(db, "users")
const getAllUsers = async () => {
const data = await getDocs(usersCollectionRef)
setAllUsers(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
}
useEffect(() => {
getAllUsers()
}, [])
const getRecieverDetails = (phone) => {
const receiver = allUsers.filter(u => u.phone === phone)[0]
setRecieverDetails(receiver)
}
const makeTransaction = async () => {
getRecieverDetails(receiverphone)
console.log(receiverDetails) --------> prints {}
const transactionsCollectionRef = collection(db, "transactions")
await addDoc(transactionsCollectionRef,
{
toUser: receiverDetails.uid,
//other data
}
)
}
return (
<div>
<h2>Send money</h2>
<input placeholder='phone number' onChange={e => setReceiverphone(e.target.value)} />
<input type="number" onChange={e => setAmount(e.target.value)} />
<button onClick={makeTransaction}>send money</button>
</div>
)
}
export default SendMoney
My guess is that the addDoc function is called before the receiverDetails gets populated with data. I am not sure how to fix this bug
Calls to setState or the setter of a useState hook are asynchronous.
Don't use state to pass data between your own pieces of code, but instead use normal variables, and promises or async/await to synchronize.
const SendMoney = () => {
const [receiverDetails, setRecieverDetails] = useState({})
const [allUsers, setAllUsers] = useState([])
const [receiverphone, setReceiverphone] = useState('')
let users; // 👈 new variable
const usersCollectionRef = collection(db, "users")
const getAllUsers = async () => {
const data = await getDocs(usersCollectionRef)
users = data.docs.map((doc) => ({ ...doc.data(), id: doc.id })); // 👈 This is synchronouse
setAllUsers(users); // 👈 This is asynchronous
}
useEffect(() => {
}, [])
const getRecieverDetails = (phone) => {
await getAllUsers()
const receiver = users.filter(u => u.phone === phone)[0]
setRecieverDetails(receiver)
}

Resources