passing-through values to a fetch call in a useEffect in react - javascript

I'm getting geolocation from the user's browsers that work fine I can display the lon and lat on my screen but as soon as I try to push my data location to a fetch call in my useEffect, I not really what I did wrong...I get the error TypeError: Cannot read property 'photo' of undefined It seems that like the data is not being pushed to the fetch or the lon and lat may be empty in this case .can someone please kindly help
import React, { useEffect, useState } from 'react';
import './App.css';
import Map from './Componets/Map/Map';
import Location from './Componets/Api/Location';
import List from './Componets/List/List';
import Test from './Componets/test/Test';
require('dotenv').config();
const App = () => {
const [
Locations,
setLocations
] = useState([]);
const [
GoeLocationlng,
setGoeLocationlng
] = useState('');
const [
GoeLocationlat,
setGoeLocationlat
] = useState('');
const [
Imgdata,
setImgdata
] = useState([]);
const [
search,
setSearch
] = useState('');
const [
query,
setQuery
] = useState('bar');
useEffect(
() => {
async function example(lon, lat) {
let response1 = await fetch(
`https://www.flickr.com/services/rest/?method=flickr.photos.search&api_key=9c348b767f7a0403e907b0788188afba&text=${query}&tags=new&accuracy=+11&media=photos+&geo_context=1&per_page=20&page=1&lat=${parseFloat(
lat
)}&lon=${parseFloat(lon)}&radius=10&radius_units=km&format=json&nojsoncallback=1`
);
let json = await response1.json();
const promises = json.photos.photo.map((i) =>
fetch(
`https://www.flickr.com/services/rest/?method=flickr.photos.geo.getLocation&api_key=9c348b767f7a0403e907b0788188afba&photo_id=${i.id}&format=json&nojsoncallback=1`
)
);
const response2 = await Promise.all(promises);
const json2 = await Promise.all(response2.map((res) => res.json()));
return {
dataset1: json,
dataset2: json2
};
}
example(GoeLocationlng, GoeLocationlat)
.then((i) => {
setLocations(i.dataset1.photos.photo);
// console.log(i.dataset2.photo);
setImgdata(i.dataset2);
})
.catch((err) => {
console.log(err);
});
getLocation();
},
[
query
]
);
const updateSearch = (event) => {
setSearch(event.target.value);
};
const getSearch = (event) => {
event.preventDefault();
setQuery(search);
// setLocations({});
setSearch('');
};
const getLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(getCods);
} else {
alert('Geolocation is not supported by this browser.');
}
};
const getCods = (postion) => {
setGoeLocationlat(postion.coords.latitude);
setGoeLocationlng(postion.coords.longitude);
};
getLocation();
return (
<div className="App">
<Map
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=AIzaSyA8i9z0T-J6oIs6Rrb7FUqz0rM1jipwrEg&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
Locations={{ Imgdata }}
/>
<form onSubmit={getSearch} className="searchForm">
<input className="search-bar" type="text" onChange={updateSearch} />
<button className="search-btn" type="submit" value="Search">
Search
</button>
</form>
{/* {Locations.map((location) => <Location key={location.id} title={location.title} />)} */}
{Locations.map((location) => (
<List
key={location.id}
title={location.title}
farm={location.farm}
server={location.server}
id={location.id}
secret={location.secret}
/>
))}
<h1>{GoeLocationlng}</h1>
</div>
);
};
export default App;

You should check your api again, it's not working correctly. It causes the error TypeError: Cannot read property 'photo' of undefined.

Related

How to render data from an array created with "reduce()"

Hook and then map is my possible solution but i need to know how
Well I'm using react and firestore so, the data fetch is saved in a hook called "Asistencias"
well my target it was to get a group of weeks with the same number and collect data by that week, n i get it, but now i would like to render that data, so I need help.
this is the response with the function with reduce
export const Presupuesto = () => {
const auth = getAuth()
const dato =auth.currentUser;
const [Presupuestos, setPresupuesto] = useState([]);
const [Asistencias, setAsistencias] = useState([]);
const [itinerante, setItinerante] = useState([])
const getPresupuestos =async () => {
const q = query(collection(db, "asignaciones"),where("asistencias", "!=", [] ))
await onSnapshot(q, (query)=>{
const data=[]
query.forEach((doc)=>{
data.push(doc.data())
})
setPresupuesto(data)
}) }
useEffect(()=>{
getPresupuestos()
},[])
console.log("hook: ", Asistencias);
const AsistenciasPresupuesto = (props) => {
return props.reduce((past, current)=>{
const foundItem = past.find(it => it.semana === current.semana)
console.log('past:', past);
if (foundItem ){
foundItem.data=foundItem.data
?[...foundItem.data, {'trabajador': current.trabajador,'entrada':current.entrada, 'salida': current.salida}]
:[{ 'trabajador': current.trabajador,'entrada':current.entrada, 'salida': current.salida }]
}else{ past.push( {
'semana': current.semana,
'data': [{
'trabajador': current.trabajador,'entrada':current.entrada, 'salida': current.salida
}]
} ) }
return past;
}, [])}
AsistenciasPresupuesto(Asistencias)
return (
<Card>
<div className='presupuestos'>
{
Presupuestos.map((presupuesto)=>(
<Button variant="danger"
id={presupuesto.obra}
className={presupuesto.obra}
value={presupuesto.presupuesto}
onClick={
(e)=>{
e.preventDefault()
console.log("objeto completo:", presupuesto.asistencias)
setAsistencias(presupuesto.asistencias)
console.log("asistencias:", Asistencias)
}} > {presupuesto.presupuesto} </Button>))
}
</div>
<div>
<Card id="prueba" className='lg'>
{/*
i would like to render here! */}
</Card>
</div>
</Card>
)
}
this is my code
this is the render

Passing arguments to Custom Hook onClick

I have a simple react app in which I am fetching the data using jsonplaceholder API and displaying the data with a delete button. I have a function deleteUser inside the User.js component. Now I want to make this deleteUser function a general function so I created a separate hook for it.
Now I want to pass arguments to that custom hook but I get the error
React Hooks must be called in a React function component or a custom
React Hook function react-hooks/rules-of-hooks
userDelete.js
import { useFetch } from "./useFetch";
export const useDelete = (userName) => {
const { data, setData} = useFetch();
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log(newData);
setData(newData)
};
useFetch.js
import { useState, useEffect } from "react";
export const useFetch = () => {
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const url = `https://jsonplaceholder.typicode.com/users`;
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const data = await response.json();
console.log(data);
setData(data);
setLoading(false);
return;
} catch (error) {
console.log("Error", error);
}
};
useEffect(() => {
fetchData();
}, []);
return { loading, data, setData };
};
User.js
import { useFetch } from "../Hooks/useFetch";
import { useDelete } from "../Hooks/useDelete";
const Users = () => {
const { loading, data, setData } = useFetch();
const deleteCallback = useDelete(data);
const deleteUser = (userName) => {
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log("newData", newData);
setData(newData);
};
return (
<>
<h1>Custom Hook Example</h1>
{loading && <h4>Fetching Data...</h4>}
{data.map((data, index) => (
<div
key={index}
style={{
border: "2px solid red",
width: "fit-content",
margin: "0 auto"
}}
>
<p>Name: {data.name}</p>
<article>Email: {data.email}</article>
{/* <button onClick={(e) => deleteUser(data.name, e)}>Delete</button> */}
<button onClick={() => useDelete(data.name)}>Delete</button>
</div>
))}
{data.length === 0 && (
<>
<p>No Items to Show</p>
</>
)}
</>
);
};
export default Users;
What am I doing wrong ?

How to destructure into global variables from inner function? (ReactJS)

I have a react functional-based component that needs some pieces of information lat and lng to pass into my Autocomplete component. I am trying to get lat and lng from an inner function but i couldnt. I tried doing
{ lat, lng } = getLatLng(results[0])
but it throws some syntax error, so I also tried
lat = getLatLng(results[0].lat)
lng = getLatLng(results[0].lng)
but it doesnt seem to work. This seems like such a simple issue but i cant figure out why. I tried putting the var keyword in front as well but it didnt work, nor did i expect it to. Below is my whole code for the component.
import usePlacesAutocomplete, { getGeocode, getLatLng } from "use-places-autocomplete"
import { useDispatch } from "react-redux";
import { setOrigin, setDestination } from '../../Slices/originDestinationSlice'
import TextField from '#mui/material/TextField';
import Autocomplete from '#mui/material/Autocomplete';
export const StartPlaces = () => {
const dispatch = useDispatch()
const { ready, value, setValue, suggestions: { status, data }, clearSuggestions } = usePlacesAutocomplete();
const handleSelect = async (val, selectedValue) => {
setValue(val, true);
// clearSuggestions();
const results = await getGeocode({ address: val });
// { lat, lng } = getLatLng(results[0])
lat = getLatLng(results[0].lat)
lng = getLatLng(results[0].lng)
}
return <>
<h4>Enter Origin</h4>
<Autocomplete
id="free-solo-demo"
freeSolo
options={data.map(({ description }) => description)}
onChange={(event, value) => {
dispatch(setOrigin({
coordinates: { lat, lng },
name: value
}))
}}
renderInput={(params) => <TextField {...params} label="Origin" onChange={(e) => handleSelect(e.target.value)} placeholder="e.g. Las Vegas" />}
sx={{ width: 300 }}
/>
</>
}
Any help would be greatly appreciated. thank you in advance!!
you should save your lat e lng in a state to use them correctly
try to change your code like this
import usePlacesAutocomplete, { getGeocode, getLatLng } from "use-places-autocomplete"
import React, {useState} from 'react'
import { useDispatch } from "react-redux";
import { setOrigin, setDestination } from '../../Slices/originDestinationSlice'
import TextField from '#mui/material/TextField';
import Autocomplete from '#mui/material/Autocomplete';
export const StartPlaces = () => {
const dispatch = useDispatch()
const { ready, value, setValue, suggestions: { status, data }, clearSuggestions } = usePlacesAutocomplete();
const [lat, setLat] = useState(0)
const [lng, setLng] = useState(0)
const handleSelect = async (val, selectedValue) => {
setValue(val, true);
// clearSuggestions();
const results = await getGeocode({ address: val });
const {lat, lng} = getLatLng(results[0])
setLat(lat)
setLng(lng)
}
return <>
<h4>Enter Origin</h4>
<Autocomplete
id="free-solo-demo"
freeSolo
options={data.map(({ description }) => description)}
onChange={(event, value) => {
dispatch(setOrigin({
coordinates: { lat, lng },
name: value
}))
}}
renderInput={(params) => <TextField {...params} label="Origin" onChange={(e) => handleSelect(e.target.value)} placeholder="e.g. Las Vegas" />}
sx={{ width: 300 }}
/>
</>
}

Consuming API in React

I am trying to consume an API in my react but I can't seem to load the response on my react frontend.
when I check the network on my browser, I can see the response, but it does not display on the web page.
my code is below can't seem to know what's wrong.
import { useState, useEffect } from "react";
import axios from "axios";
import "./PrivateScreen.css";
const PrivateScreen = ({ history }) => {
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState(null);
const url = "https://jsonplaceholder.typicode.com/users";
useEffect(() => {
if(!localStorage.getItem("authToken")) {
history.push("/login")
}
const fetchPrivateDate = async () => {
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("authToken")}`,
},
};
try {
await axios.get(url, config)
.then(res => {
setPrivateData(res.data);
});
} catch (error) {
localStorage.removeItem("authToken");
setError("You are not authorized. Please login");
}
};
fetchPrivateDate();
}, [history]);
const logoutHandler = () => {
localStorage.removeItem("authToken");
history.push("/login");
};
return error ? (
<span className="error-message">{error}</span>
) : (
<>
<div style={{ background: "green", color: "white" }}>
{privateData.name}
</div>
<div><p>hello from this side</p></div>
<button onClick={logoutHandler}>Log Out</button>
</>
);
};
export default PrivateScreen;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
First you must change instead of
const [privateData, setPrivateData] = useState(null);
const [privateData, setPrivateData] = useState([]);
when calling the array data we want initialize an empty array
Then second when we are showing array data with help map method we want to call like this,Let me know issue is fixed
{privateData.map((privateDatas) => (
<div style={{ background: "green", color: "white" }}>
{privateDatas.name}
</div>
))}

try to end up search filter with react but there is mistake

This is my main component for seraching:
import React, {useState, useEffect} from 'react';
import SearchBar from "./SearchBar";
import SearchList from "./SongList";
const SearchMusic = (props) => {
const [input, setInput] = useState('');
const [songListDefault, setSongListDefault] = useState();
const [songList, setSongList] = useState();
const fetchData = async () => {
return await fetch('http://ws.audioscrobbler.com/2.0/?method=tag.gettoptracks&tag=disco&api_key=c17b1886d9465542a9cd32437c804db6&format=json')
.then(response => response.json())
.then(data => {
setSongList(data)
setSongListDefault(data)
});
}
const updateInput = async (input) => {
const filtered = songListDefault.filter(song => {
return song.name.toLowerCase().includes(input.toLowerCase())
})
setInput(input);
setSongList(filtered);
}
useEffect(() => {
fetchData()
}, [])
return (
<div>
<h1>Song List</h1>
<SearchBar
input={input}
onChange={updateInput}
/>
<SearchList songList={songList}/>
</div>
);
};
export default SearchMusic;
below is separate input js file:
import React from 'react';
const SearchMusic = ({keyword, setKeyword}) => {
const BarStyling = {width: "20rem", background: "#F2F1F9", border: "none", padding: "0.5rem"};
return (
<input
type="text"
style={BarStyling}
key='random1'
value={keyword}
placeholder={'Search a song'}
onChange={(e => setKeyword(e.target.value))}
/>
);
};
export default SearchMusic;
end it is my song list below:
import React from 'react';
const SongList = ({songList = []}) => {
return (
<div>
{
songList && songList.tracks.track.map((song, index) => {
if (song) {
return (
<div key={song.name}>
<h1>{song.name}</h1>
</div>
)
}
return null;
}
)
}
</div>
);
};
export default SongList;
I get this mistake --> TypeError: setKeyword is not a function. I don't what's wrong and don't know how to get rid of it. It seems to me problem is in updateInput function more precisely in what it returns --> song.name.toLowerCase(). There is api link:
http://ws.audioscrobbler.com/2.0/?method=tag.gettoptracks&tag=disco&api_key=c17b1886d9465542a9cd32437c804db6&format=json
I need to get name of a song in search input... But something's wrong
The props that this component are expecting are not getting passed into component in your parent component
const SearchMusic = ({keyword, setKeyword}) => {
const BarStyling = {width: "20rem", background: "#F2F1F9", border: "none", padding: "0.5rem"};
return (
<input
type="text"
style={BarStyling}
key='random1'
value={keyword}
placeholder={'Search a song'}
onChange={(e => setKeyword(e.target.value))}
/>
);
};
That is assuming that the following is the above component
<SearchBar
input={input}
onChange={updateInput}
/>
How about
<SearchBar
keyword={input}
setKeyword={updateInput}
/>

Categories

Resources