I have an array of Names(Commented in code):=
export default Main_homepage = (props) => {
var Names = []
useEffect(() => {
fetch('https://www.amrutras.com/Items.php')
.then((response) => response.json())
.then((responseJson) => {
{
Names = responseJson //***Names Array***
console.log(Names[0].ID) //****Its working, I am getting outpu for this in console
console.log(Names[0].Name)
}
})
.catch((error) => {
console.error(error)
})
})
return(
<View>{console.log(Names[0].ID)}</View> //****Its not working.
)
}
But when I am trying to access outside of the use effect it's not working.
In short, I am trying to access the response array in JSX.
As suggested by Praveen Kumar sir, utilize useState hook.
Here is the Full Working Example: Expo Snack
import React, { useEffect, useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
export default App = (props) => {
const [names, setNames] = useState([]);
useEffect(() => {
fetch('https://www.amrutras.com/Items.php')
.then((response) => response.json())
.then((responseJson) => {
{
console.log(responseJson);
setNames(responseJson); //***Names Array***
}
})
.catch((error) => {
console.error(error);
});
}, []);
return (
<View style={{ marginTop: Constants.statusBarHeight }}>
<Text>{JSON.stringify(names)}</Text>
</View>
);
};
So this is an asynchronous call and it will not work because after the return statement is sent out, the value gets changed.
Change Names into a state hook - Using the State Hook:
// Remove this
// var Names = []
// Replace with:
const [Names, setNames] = useState([]);
And when you're updating, use setNames:
// Remove this inside the promise
// Names = responseJson
// Replace with the following:
setNames(Names);
If you want to understand what an asynchronous call, read more at How do I return the response from an asynchronous call?
Related
I'm building MERN stack app wherein when logged in as Admin it will render all products in a table and when logged in as Not Admin it will render active products in cards.
I'm trying to do multiple fetch data in my Products.js page
//Products.js
import { Fragment, useEffect, useState, useContext } from "react";
import { Container, Table } from "react-bootstrap";
import ProductCard from "../components/ProductCard";
import UserContext from "../UserContext";
export default function Products() {
const { user } = useContext(UserContext);
const [userProducts, setUserProducts] = useState([]);
const [adminProducts, setAdminProducts] = useState([]);
// FETCH DATA
useEffect(() => {
fetchAdminProducts();
}, []);
useEffect(() => {
fetchUserProducts();
}, []);
const fetchAdminProducts = () => {
fetch("http://localhost:4000/products/all")
.then((res) => res.json())
.then((data) => {
setAdminProducts(data);
});
};
const fetchUserProducts = () => {
fetch("http://localhost:4000/products/")
.then((res) => res.json())
.then((data) => {
setUserProducts(data);
});
};
return (
<Fragment>
<Container>
{user.isAdmin === true ?
(...) :
(...)}
</Container>
</Fragment>
);
}
Am I doing it correctly?
How do I map Admin products in a table and User products in a card?
What is the best approach to fetch multiple data and render it conditionally when logged in?
Thanks for the help guys!
try to check the user role inside the useEffect
//Products.js
import { Fragment, useEffect, useState, useContext } from "react";
import { Container, Table } from "react-bootstrap";
import ProductCard from "../components/ProductCard";
import UserContext from "../UserContext";
export default function Products() {
const { user } = useContext(UserContext);
const [userProducts, setUserProducts] = useState([]);
const [adminProducts, setAdminProducts] = useState([]);
// FETCH DATA
useEffect(() => {
if(user.isAdmin){ // <-- check if is Admin
fetchAdminProducts();
} else{
fetchUserProducts();
}
}, []);
const fetchAdminProducts = () => {
fetch("http://localhost:4000/products/all")
.then((res) => res.json())
.then((data) => {
setProducts(data);
});
};
const fetchUserProducts = () => {
fetch("http://localhost:4000/products/")
.then((res) => res.json())
.then((data) => {
setProducts(data);
});
};
return (
<Fragment>
<Container>
{user.isAdmin === true ?
(...) :
(...)}
</Container>
</Fragment>
);
}
I would recommend having one function rather than 2 and also have like a state that will make that your useEffect go off.
const [state,setState]=useState(null);
const [products,setProducts]=useState([]);
const fetchProducts = () => {
if(user ==="Admin"){
fetch("http://localhost:4000/products/all")
.then((res) => res.json())
.then((data) => {
setProducts(data);
});
setState(true);
}
else{
fetch("http://localhost:4000/products/")
.then((res) => res.json())
.then((data) => {
setProducts(data);
});
setState(false);
}
};
usEffect(()=>{
fetchProducts();
},[state])
Then the return would look like that.
return (
{state ? <Table data=products> : <Card data=products>}
)
Would recommend create a seperate component that you call Table and Card that take in products. This will make your code more neat and easier to manage.
Hope this help.
I left the code below that I got my data from. More than one request is processed at the time of refreshing the page, the reason may be why, if you can help I would appreciate it. have a nice day.
import React, { useEffect, useState } from "react";
import axios from "axios"
import Cookies from "universal-cookie"
const Entry = React.createContext();
export const EntryProvider = ({ children }) => {
const [post, setPost] = useState();
const cookie = new Cookies()
const token = cookie.get("acsess_token")
const getAll = () => {
axios.defaults.headers.common['Authorization'] = token;
const entry = axios.get("/api/entry/entry", {
headers: {
"Authorization": token
}
})
.then((response) => {
const data = response.data.data
data.map(element => {
setPost(element)
});
setPost(data)
})
.catch((err) => { console.log(err) })
}
useEffect(() => {
getAll()
},[getAll])
return (
<Entry.Provider value={{post}}>
{children}
</Entry.Provider>
);
};
export const userEntry = () => {
return React.useContext(Entry);
};
Instead adding getAll in the array dependency, remove it
useEffect(() => {
getAll()
},[getAll])
Like this:
useEffect(() => {
getAll()
},[])
Why that?
Because the useEffect will be execute it every time the component renders and because of having getAll in the dependency array it will execute it again
How can I add sorting for API returning a JSON array? I'm new to Redux. I have installed the redux. Could someone tell me what's the best method to follow?
Thanks for your help.
import React, { useState, useEffect } from "react";
import Post from "../../Components/Post/Post";
import axios from "axios";
const HomePage = () => {
const [posts, setPosts] = useState("");
let config = { Authorization: "............." };
const url = "..........................";
useEffect(() => {
AllPosts();
}, []);
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
console.log(response);
setPosts(allPosts);
})
.catch((error) => console.error(`Error: ${error}`));
};
return (
<div>
<Post className="Posts" posts={posts} />
</div>
);
};
export default HomePage;
You don't have redux here. Do you need it?
If you want to sort result and save sorted results to state:
...
.then((response) => {
const allPosts = response.data.articles;
// sort the result here
const sortedPosts = allPosts.sort((a,b) =>
// comparer
);
setPosts(sortedPosts);
})
...
I'm trying to fetch some data from an api and display it in jsx.First I get the users geolocation,then I call the fetch function which uses the users geolocation data to request the data from an api , afterwards
the received data from an api is used to set the weatherData state.The final step is where conditional rendering is used to show the h1 element depending if the state is defined or not.The problem is that my weatherData is always undefined,and when I try to display it returns as undefined error.Why is my weatherData undefined?
import react from "react";
import {useState} from "react";
import {useEffect} from "react";
const MainWeather=()=>{
{/*State for storing geolocation data*/}
const [status, setStatus] = useState(null);
const [weatherData,setWeatherData]=useState('');
{/*Fetches the data from an api*/}
const fetchData=(link)=>{
fetch(link)
.then(res => res.json())
.then(
(result)=>{
{/*Sets the weather data object*/}
setWeatherData(result);
console.log(result);
setStatus('data set');
},
(error)=>{
console.log(error)
}
)
}
{/*Retrieves the location from geolocation api*/}
const getLocation = async () => {
if (!navigator.geolocation) {
setStatus('Geolocation is not supported by your browser');
} else {
navigator.geolocation.getCurrentPosition((position) => {
{/*Calls the fetch function to get the data from an api*/}
fetchData(`https://api.openweathermap.org/data/2.5/onecall?lat=${position.coords.latitude}&lon=${position.coords.longitude}&exclude={part}&appid=0ea4f961aae42bfa56f75ca058577e1e&units=metric`);
}, () => {
setStatus('Unable to retrieve your location');
});
}
}
{/*Calls getLocation function on the first render*/}
useEffect(()=>{getLocation()},[])
console.log(status);
return(
<div>
{weatherData == 'undefined' ?
<h1>undefined</h1> :
<h1>{weatherData.current.temp}</h1> }
</div>
)
}
export default MainWeather;
I checked the code, what you have implemented is correct , if you are using a mac you should allow browser to fetch location , in windows a popup will come to allow it , might be browser issue check it again
still I made few changes in below the above code , just refer to it
import { useState, useEffect } from "react";
const MainWeather = () => {
const [status, setStatus] = useState(null);
const [weatherData, setWeatherData] = useState("");
const fetchData = (link) => {
fetch(link)
.then((res) => res.json())
.then(
(result) => {
setWeatherData(result);
setStatus("data set");
},
(error) => {
console.log(error);
}
);
};
const getLocation = async () => {
if (!navigator.geolocation) {
setStatus("Geolocation is not supported by your browser");
} else {
navigator.geolocation.getCurrentPosition(
(position) => {
fetchData(
`https://api.openweathermap.org/data/2.5/onecall?lat=${position.coords.latitude}&lon=${position.coords.longitude}&exclude={part}&appid=0ea4f961aae42bfa56f75ca058577e1e&units=metric`
);
},
() => {
setStatus("Unable to retrieve your location");
}
);
}
};
useEffect(() => {
getLocation();
}, []);
return (
<div>
{!weatherData ? (
<h1>{status}</h1>
) : (
<h1>{weatherData?.current?.temp} ℃ </h1>
)}
</div>
);
};
export default MainWeather;
You can refer to this codesandbox
I created a file Category.js
import React, { useState } from 'react'
export const CategoryData = (props) => {
const [Category, setCategory] = useState('')
fetch('https://www.amrutras.com/Category.php')
.then((response) => response.json())
.then((responseJson) => {
{
setCategory(responseJson)
// responseJson.map((item) => Alert.alert(item.Name))
}
// Showing response message coming from server after inserting records.
})
.catch((error) => {
console.error(error)
})
return Category
}
export default CategoryData
I want to use this Category const in my other component.
I tried to do that with
import CategoryData from '../consts/CategoryData'
and using this function in useEffect of another component. like this.
useEffect(() => {
console.log(CategoryData)
})
But it's not working.
You cannot use hooks directly within functions, unless they are custom hooks which you then cannot invoke inside other hooks but have to follow the rules of hooks to use them
You can restructure your code to implement CategoryData like a custom hook
export const useCategoryData = (props) => {
const [Category, setCategory] = useState('')
useEffect(() => {
fetch('https://www.amrutras.com/Category.php')
.then((response) => response.json())
.then((responseJson) => {
{
setCategory(responseJson)
// responseJson.map((item) => Alert.alert(item.Name))
}
// Showing response message coming from server after inserting records.
})
.catch((error) => {
console.error(error)
})
}, [])
return Category
}
export default useCategoryData;
Now you can use it in your component like
function App () {
const categoryData = useCategoryData();
...
}
SOLUTION2:
Another way to implement this is to not use custom hook but implement a normal function like
export const CategoryData = (props) => {
return fetch('https://www.amrutras.com/Category.php')
.then((response) => response.json())
})
.catch((error) => {
console.error(error)
})
}
export default CategoryData
and use it like
function App () {
const [categoryData, setCategoryData] = useState(null);
useEffect(() => {
CategoryData.then(res => setCategoryData(res));
}, []); Make sure to provide a dependency list to your useEffect otherwise you will end up in a infinite loop
}
Make it as a custom hook
import React, { useState } from 'react'
export const useCategoryData = (props) => {
const [Category, setCategory] = useState('')
useEffect(()=>{
fetch('https://www.amrutras.com/Category.php')
.then((response) => response.json())
.then((responseJson) => {
{
setCategory(responseJson)
// responseJson.map((item) => Alert.alert(item.Name))
}
// Showing response message coming from server after inserting records.
})
.catch((error) => {
console.error(error)
})
},[])
return {Category}
}
import it like
import {useCategoryData} from '.......'
const {Category} = useCategoryData()