orderByKey is not a function in reactjs expo? - reactjs

I am trying to randomize the node to be picked by firebase realtime database but I am only able to get it to randomize a cuisine and not cuisine + store
The code currently is : It only can randomize cuisine but for the store it is getting, it is getting empty [] in my console
import { StyleSheet, Text, View } from 'react-native'
import {db} from '../firebase'
import React, {useEffect, useState} from 'react'
import {ref, get} from 'firebase/database'
const SubScreen2 = () => {
const [todoData, setToDoData] = useState([])
useEffect (() => {
get(ref(db, "food/Total")).then(snapshot => {
const count = snapshot.val();
const random = Math.floor((Math.random() * count));
return get(ref(db, `food/`).orderByKey().limitToFirst(random + 1))
}).then(snapshot => {
const randomKey = Object.keys(snapshot.val())[random];
setToDoData(snapshot.val()[randomKey]);
}).catch(error => {
console.log(error);
})
}, [])
console.log(todoData)
return (
<View style={styles.container}>
{todoData ? (
<View>
<Text>{todoData.Description}</Text>
<Text>{todoData.Location}</Text>
<Text>{todoData.Halal}</Text>
<Text>{todoData.OH}</Text>
</View>
) : (
<Text>Loading...</Text>
)}
</View>
)
}
export default SubScreen2
Here is my console logs that shows the cuisine being randomly picked and the error :
Part of my database:
{
"food": {
"Bakery": {
"Bakery Cuisine": {
"Description": "Within North Spine Plaza",
"Halal": "Yes",
"Location": "50 Nanyang Ave, #01-20 North Spine Plaza, Singapore 639798",
"OH": "Mon - Sat : 8 AM to 7 PM, Sun Closed"
}
},
"Beverage": {
"Beverage": {
"Description": "Within the South Spine food court",
"Halal": "No",
"Location": "21 Nanyang Link, Singapore 637371",
"OH": "Mon - Fri: 7 30 am to 8 pm, Sat - Sun/PH Closed"
},
"Beverages": {
"Description": "Within North Spine Koufu",
"Halal": "No",
"Location": "76 Nanyang Dr, #02-03 North Spine Plaza, Singapore 637331",
"OH": "Mon - Fri : 7 am to 8 pm, Sat : 7 am to 3 pm, Sun Closed"
},
"Boost": {
"Description": "Within North Spine Plaza",
"Halal": "No",
"Location": "50 Nanyang Ave, #01-11 North Spine Plaza, Singapore 639798",
"OH": "Mon - Fri : 10 am to 9 pm, Sat - Sun: 10 am to 6 pm"
},
"Total": 120,

Looks like you have a mix of V8 and V9 syntax.
Update your imports
import {ref, get, query, orderByKey, limitToFirst} from 'firebase/database'
Then use the query class sorted, filtered, etc.
return get(query(ref(db, 'food/'), orderByKey(), limitToFirst(random + 1)));
Docs: https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data

Related

How to Set States Inside Loop React Nextjs

I have a functions that should update data provided by the user. But due to some strange reason its only updating first value of quizzes. Its not updating Topic value and when adding second value to quizzes it revert backs to 1st value.
Data
[
{
"Topic": [ "Biology", "Introduction to Biology" ],
"Question": "Example of micro molecule is:",
"Quizzes" : ["2022 Biology Geek", "General Knowledge"]
},
{
"Question": "Pepsin enzyme works in;"
}
]
Code
const [finalData, setFinalData] = useState({
TOPIC: [],
QUIZZES: []
})
const setData = () => {
const ei = userSelectedData.topic;
const yr = userSelectedData.quiz
selectedDocsID.forEach(doc => {
fetchDoc("ques", doc)
.then((response) => {
const TField = response["Topic"]
const QField = response["Quizzes"]
const newTs = new Set([...finalData.TOPIC]);
const newQs = new Set([...finalData.QUIZZES]);
//If Topic Field Does not Exist
if (TField == undefined) {
newTs.add(doc);
setFinalData({ ...finalData, EI: Array.from(newTs) })
}
//If Topic Field Exist But Don't have Requried Value
else if (TField.includes(ei) != true) {
newTs.add(doc);
setFinalData({ ...finalData, EI: Array.from(newTs) })
}
//If Quiz Field Does not Exist
if (QField == undefined) {
newQs.add(doc);
setFinalData({ ...finalData, YR: Array.from(newQs) })
}
//If Quiz Field Exist But Don't have Requried Value
else if (QField.includes(yr) != true) {
newQs.add(doc);
setFinalData({ ...finalData, YR: Array.from(newQs) })
}
})
});
}
<Button onClick={() => setData()}>Update Data</Button>
Current Result
//Displaying Results by console.log inside useEffects Hook
{
"TOPIC": [],
"QUIZZES": [
"2022 Biology Geek",
"General Knowledge"
]
}
//After Few Seconds
{
"TOPIC": [],
"QUIZZES": [
"2022 Biology Geek"
]
}
Expected Result
{
"TOPIC": ["Biology"],
"QUIZZES": [
"2022 Biology Geek",
"General Knowledge"
]
}

Fetching , rendering and sorting data in Reactjs

How can i fetch data from a json file and render them in an ascending order? For example let´s say i have this json file
[{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}
and i want to render the data with only Id and name in ascending order.
I tried coding it in different ways but since i am still a beginner i can´t really figure it out. Thank you so much
You can use .map and .sort:
const data = [{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}]
const sorted = data.map(d => ({id: d.id, name: d.name})).sort((el1, el2) => el1.id - el2.id)
console.log(sorted)
Once you set the new sorted and mapped array to a state variable, you can map over it to render.
Example
//Functional Component:
const Example = ({data}) => {
const [sortedData, setSortedData] = useState([])
useEffect(() => {
if(data) setSortedData(data
.map(d => ({id: d.id, name: d.name}))
.sort((el1, el2) => el1.id - el2.id)))
}, [data])
return(
sortedData?.map(element => <div key={element.id}> {element.name} </div>)
)
}
You can short your array data using the .sort method.
App.js
import React, { useState, useEffect } from "react";
import Data from "./data.json";
function App() {
const [data, setData] = useState();
const sortDataByField = (array, field) => {
return array.sort((a, b) =>
a[field].toString().localeCompare(b[field].toString())
);
};
useEffect(() => {
const sortData = sortDataByField(Data, "name");
setData(sortData);
}, []);
return (
<div className="App">
{data?.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
export default App;
data.json
[{
"id": 0,
"name": "Vernon Dunham",
"company": "Qualcore",
"email": "vernon.dunham#qualcore.com"
}, {
"id": 1,
"name": "Dori Neal",
"company": "Sunopia",
"email": "dori.neal#sunopia.com"
}, {
"id": 2,
"name": "Rico Muldoon",
"company": "Airconix",
"email": "rico.muldoon#airconix.com"
}]
Import and set up a useState hook
import React, {usesState} from 'react'
const [companies, setCompanies] = useState([])
fetch the data
const data = fetch('/api/v1/companies', {method: 'GET'})
sort first to order, then map to only get id and name
const sorted = data.sort((a, b)=>{return a.name > b.name ? 1 : -1})
.map(({id, name}) => {return {id, name}})
/* this return only id and name sorted by name
*
* if you wanna sort by id, do this:
* .sort((a, b) => a.id - b.id)
*/
When you done sorting and mapping, store it to that useState hook so that you can render it:
setCompanies(sorted)
Then render it, also prevent errors by checking if you state has data before rendering:
companies &&
companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
// or
companies
? companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
: <p>No data</p>
All code
import React, {usesState, useEffect} from 'react'
export default App = () =>{
const [companies, setCompanies] = useState([])
useEffect(()=>{
fetchData()
}, [])
const fetchData = async () => {
try{
const data = fetch('/api/v1/companies', {method: 'GET'})
if(data){
const sorted = data.sort((a, b)=>{return a.name > b.name ? 1 : -1})
.map(({id, name}) => {return {id, name}})
setCompanies(sorted)
}
else{
console.log('No data')
}
}
catch (err){
console.log(err)
}
}
return(
<div>
companies &&
companies.map(({id, name}) => <h1 key={id}>{name}</h1>)
</div>
)
}

star wars api, how do I get values from api?

I'm using the https://swapi.dev/api/people/ and I'm having an interesting issue with an api I haven't encountered before. Here is an example response of the first value form the api using https://swapi.dev/api/people/
[
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "http://swapi.dev/api/planets/1/",
"films": [
"http://swapi.dev/api/films/1/",
"http://swapi.dev/api/films/2/",
"http://swapi.dev/api/films/3/",
"http://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [
"http://swapi.dev/api/vehicles/14/",
"http://swapi.dev/api/vehicles/30/"
],
"starships": [
"http://swapi.dev/api/starships/12/",
"http://swapi.dev/api/starships/22/"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "http://swapi.dev/api/people/1/"
},
]
The value I want to get is the first value of the films array, which I can achieve however its just a url. I'd need to somehow grab that url, make an api call with it and then get the first film. An example response after calling the api for the first value of films looks like this:
{
"title": "The Empire Strikes Back",
"episode_id": 5,
"opening_crawl": "It is a dark time for the\r\nRebellion. Although the Death\r\nStar has been destroyed,\r\nImperial troops have driven the\r\nRebel forces from their hidden\r\nbase and pursued them across\r\nthe galaxy.\r\n\r\nEvading the dreaded Imperial\r\nStarfleet, a group of freedom\r\nfighters led by Luke Skywalker\r\nhas established a new secret\r\nbase on the remote ice world\r\nof Hoth.\r\n\r\nThe evil lord Darth Vader,\r\nobsessed with finding young\r\nSkywalker, has dispatched\r\nthousands of remote probes into\r\nthe far reaches of space....",
"director": "Irvin Kershner",
"producer": "Gary Kurtz, Rick McCallum",
"release_date": "1980-05-17",
}
I've never used an api that has urls as values, any ideas on how this might work?
Here is my current code:
Page.jsx
import React, {useState, useEffect} from 'react';
import '../css/Page.css';
import axios from 'axios';
const Page = () => {
const [data, setData] = useState([]);
const fetchData = async () => {
try {
const res = await axios.get(
"https://swapi.dev/api/people/"
);
setData(res?.data.results);
} catch (error) {
console.log(error);
}
}
useEffect(() => {
fetchData();
}, [])
const mapData = () => {
if(data && data.length > 0) {
return (
<>
{data.map(item => (
<div className="itemContainer" key={item.name}>
<div className="image"><img src="" alt=""/></div>
<div className="content">
<span className="title">Name: </span><span className="name">{item.name}</span>
<br />
<span className="title">Birthyear: </span><span className="name">{item.birth_year}</span>
<br />
<span className="title">Homeworld: </span><span className="name">{item.homeworld}</span>
</div>
</div>
))}
</>
)
}
}
return (
<div className="container">
{mapData()}
</div>
);
}
export default Page;

Add an additional property and value to a state object when transfering from one state to another. [Hooks]

I'm building a e commerce meal ordering app. Trying to learn more advanced React.
I would like to add a quantity increment when the user adds more than one of the same item to order state.
I have some 'products' like this:
[
{
"description": "A rich blend, roasted for depth, smoothness and full body our coffee is harvested at the height of the season when the coffee cherry is at perfect ripeness, and sun dried in the fresh mountain air. ",
"price": 4.5,
"SKU": 1,
"name": "Ethiopian"
}
]
On click of a button the 'drink' is added to my order state.
const [order, setOrder] = useState([]);
With this function:
const addToOrder = product => {
setOrder([...order, product]);
};
And the state data looks like this once transferred.
[
{
description": "This coffee has been lovingly slow-roasted to develop flavours of smooth milk chocolate and gentle citrus for a soft, easy-going character. It's perfect for weekend relaxation.",
"price": 4.5,
"SKU": 3,
"name": "Kenyan"
}
]
Function being called
<button onClick={() => addToOrder(product)}>Add to Order</button>
My problem is that I want to add a quantity value to this order state so the user can order several of the same 'coffee'. And each time the user add the coffee the quantity is incremented.
You can do a reference checking by SKU.
quantity field is set to 1 for first order
else incremented on additional orders.
const addToOrder = product => {
setOrder(prevOrders => (
prevOrders.map(order => (
order.SKU === product.SKU ?
{ ...order, quantity: order.quantity + 1 }
: { ...product, quantity: 1 }
))
));
};
Other way of setting quantity is via useState if all products are fetched on init.
const [order, setOrder] = useState(() => (
props.products.map(product => (
{ ...product, quantity: 1 }
))
);
const addToOrder = product => {
setOrder(prevOrders => (
prevOrders.map(order => (
order.SKU === product.SKU ?
{ ...order, quantity: order.quantity + 1 }
: order
))
));
};

How to access data returned from props

I new to nextjs and react. I am using the nextjs to fetch data from api and display it in view. this is my code.
const Index = props => (
<Layout>
<h1>Events</h1>
<ul>
{props.eventList.map(({ venue }) => (
<li key={venue.name}>
<a>{venue.name}</a>
</li>
))}
</ul>
</Layout>
);
Index.getInitialProps = async function() {
const res = await fetch("api link here");
let data = await res.json();
console.log(`Show data fetched. Count: ${data.events.length}`);
return {
eventList: data.events
};
};
Now my api return data like this
[
{
"id": 4303920,
"name": "Test Event",
"venue": {
"id": 1610,
"name": "Eiffel Tower Viewing Deck at Paris Las Vegas",
}
},
{
"id": 4323,
"name": "Test Event 2",
"venue": {
"id": 1610,
"name": "Eiffel Tower Viewing Deck at Paris Las Vegas",
}
}
]
I am able to access the venue details by props.eventList.map function but i am not able to access the id and name.
In your map instead of ({venue}) => just do (item) => your issue is you are getting each element and only extracting venue from it instead of the entire element. Once you have item you can say item.id, item.venue etc.
You should not put {venue} inside your map function but pass the event like this (event) then you will have even.name and event.is and you will have event.venue.id and event.venue.name

Resources