React usestate is not updating even after using useeffect - reactjs

I am using usestate, but it not updating even if i am using useeffect. i wanted to show grid once call to backend is complete
const backendData: any = useSelector((state: RootState) => state.backendData);
const [isLoading, setIsLoading] = useState(false);
const [data, setBackendData] = useState(backendData);
//once call to backend is complete, backendData gets updated
useEffect(() => {
setBackendData(backendData);
setIsLoading(false);
}, [backendData]);
useEffect(() => {
setIsLoading(isLoading);
}, [isLoading]);
const onSearchButtonClick = () => {
setIsLoading(true); //when i set isloading to true it is not updating even if i have useeffect
//call to backend
getSearchDetails();
if (!isLoading) { //i wanted to show grid once call to backend is complete
//but this is always false and grid is displaying before call to backend is complete
setGridShow(true);
}
};

Related

useState doesn't re-initialize after fetch

I'm trying to initialize a useState based on a variable user.x that is fetched from the data base but the problem is, useState will initialize before the fetch and not after the fetch. So the value in useState is always initialized as undefined.
function foo () {
const [user, setUsers] = useState([])
useEffect(() => {
fetch("Some URL to fetch from")
.then(res=>res.json())
.then((result)=>{
setUsers(result);
})
},[])
const [check, setCheck] = useState(() => {
if (user.x == "No") {
return false;
}
return true;
});
}
I know useEffect is what rerender the page and we can't use Axios because it messes with the other code. So is there a way to force useState to rerender after useEffect fetching or fetch without axios and useEffect?
You could use another useEffect triggered by the changes in your user state variable like so:
const [check, setCheck] = useState(False);
useEffect(() => {
setCheck(user.x !== "No");
}, [user, setCheck]);
This effect depends on user so it triggers when that state changes and updates your check state.

How to fix loading spinner when using useEffect Hooks with dependency list?

I am facing one problem when trying to add a spinner.
My problem is when I add "product" dependency in useEffect hooks then my loading spinner always spinning and data not showing.
Here is my code :
const [product, setProduct] = useState([]);
const [msg, setMsg] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
// show all products on the manage inventory page
useEffect(() => {
setLoading(true);
(async () => {
const data = await fetchAllProduct();
if (data) {
setProduct(data);
setLoading(false);
}
})();
}, [product]);
Bellow the return code >>
{
loading === false ? <ProductTable
viewProductHandle={viewProductHandle}
deleteProductHandle={deleteProductHandle}
product={product}>
</ProductTable> : <Spinner></Spinner>
}
So how do I fix that? pls, help me...
It's happening because you're only setting your loading state to false when data is a truthy. Moreover, your loading state can start with a true value, and you set it to false inside your useEffect after finishing the request. This way you're going to avoid initializing the state with a false value, setting it to true, and then back to false.
I also think your product state doesn't need to be on dependency array, because you're only setting it once, after the fetchAllProduct() call, so it'll probably not change again, as you're not passing setProducts down to your ProductTable component.
So your code should be something like this:
const [product, setProduct] = useState([]);
const [msg, setMsg] = useState('');
const [loading, setLoading] = useState(true);
const navigate = useNavigate();
// show all products on the manage inventory page
useEffect(() => {
(async () => {
const data = await fetchAllProduct();
if (data) {
setProduct(data);
}
setLoading(false);
})();
}, []);

ReactNative: how to refresh on data

I'm new to React Native code building.
Below is my React Native code to get data from Firebase.
const page_one = () => {
const [isLoading, setIsLoading] = useState(true)
const [placeList, setPlaceList] = useState([])
const [message, setMessage] = useState(false)
const db = firebase.firestore().collection('places')
const onLoad = async () => {
const place_ref = await firebase.firestore().collection('places').get()
if (place_ref.empty) {
setMessage(true)
return
}
const places = []
try {
place_ref.forEach(doc => {
const entity = doc.data()
entity.id = doc.id
places.push(entity)
})
setPlaceList(places)
setMessage(false)
setIsLoading(false)
return
} catch (error) {
console.log("Error:\n", error.message)
return
}
}
}
useEffect(() => {
onLoad()
console.log('place List')
}, [isLoading])
return (<View></View>)
}
I need to refresh the current component every time I render, to get newly added data from firebase. How to make possible this.
As of now component is not loading when I rendering the component 2nd time. it fetches the old data only, not loading the latest data still I refreshing the whole application.
I need to fetch the latest data whenever I render the component.
I tried with below useEffect hook:
useEffect(() => {
onLoad()
console.log('place List')
}, [isLoading, placeList])
But it calls the firebase request n number of times till I existing the current component.
I want to call the firebase request only once when ever I visiting the current component.
please help me..
As far as I understand you need to refresh whenever this component gets focused
So for that, write like this
useEffect(() => {
const unsubscribe = navigation.addListener("focus", () => {
onLoad() // Gets fired whenever this screen is in focus
});
return unsubscribe;
}, [navigation]);
Also don't forget to destructure the props to get the navigation prop
Like this
const page_one = ({ navigation }) => {
...Code Inside
}

React wont update state on useEffect

I am new in react. can anyone explain why the loading is not updating its value. on console the loading is 1
import React, { useState, useEffect } from "react";
function App() {
useEffect(() => {
hai();
}, []);
const [loading, setLoading] = useState(1);
const hai = () => {
console.log("............");
setLoading(2);
console.log(loading);
};
return <></>;
}
export default App;
Also if there are two state variables, and rearrange the set function, whole application breaks
const [loading, setLoading]=useState(false)
const [datas, setDatas]=useState([])
//works fine if loading is set second
const hai = () => {
setDatas(res) //fetched from external api
setLoading(true)
};
//throws error in applicaton
const hai = () => {
setLoading(true)
setDatas(res) //fetched from external api
};
console.log(datas)
You are testing your loading value in a wrong way,this is how you should be doing it:
useEffect(() => {
console.log(loading);
}, [loading]);
and remove console.log(loading) from the function hai
Whenever you want to access an updated value of some variable then put it inside an useEffect and put the value which you want to check inside the useEffect's dependency array.

React useState loading not changing

I run into errors attempting to display data that has not been fetched yet, so.. I want to display loading until the data is fetched, but my 'setIsLoading' always returns false even when it's set to true.
Am I missing something really obvious? I'm fairly fresh to hooks.
const Pokedex = () => {
const [data, setData] = useState({});
const [isLoading, setIsLoading] = useState(false);
const pokemonId = 1;
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
const result = await axios(
`https://pokeapi.co/api/v2/pokemon/${pokemonId}`
);
setData(result.data);
};
fetchData();
setIsLoading(false);
}, [pokemonId]);
console.log("loading: ", isLoading);
You need to change isLoading state right after the fetch request completes.
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`https://pokeapi.co/api/v2/pokemon/${pokemonId}`
);
setData(result.data);
setIsLoading(false);
};
fetchData();
}, []);
Don't rely on printing stuff outside the hooks because you won't have a real feedback. You can use render method (in the return, with JSX code) or inside the hooks.
Also, since state is reset when the component is refreshed, you can rely on initializating isLoading to true. That way you just need to change it once the request is fetched.
You can check a working demo here.
First of all, If you are calling async function, you are anonymously creating Promise<void>, so after that, good way to check if promise was successfull is to use then or catch methods from Promise API.
Example solution.
const fetchData = async () => {
setIsLoading(true);
const result = await axios(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`);
setData(result.data);
};
fetchData().then(() => {
setIsLoading(false)
})
First, I think your loading state should be initialized to true.
const [isLoading, setIsLoading] = useState(true);
And then, set the loading state to false inside the async function
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`https://pokeapi.co/api/v2/pokemon/${pokemonId}`
);
setData(result.data);
setIsLoading(false);
};
fetchData();
}, [pokemonId]);

Resources