why does useEffect not re-run having setState as dependency? - react-hooks

I don't know why useEffect doesn't re-run when I call useState dependecy, I tried to pass state as useEffect dependency but it makes an infinite loop. I would like to run useEffect just when setState is called.
is there any way to do so?
useEffect(() => {
console.log('useEffect initial state ')
fetch(API)
.then(res => res.json())
.then(response => {
setState(response.data);
})
}, [setState]);

The infinite loop is caused because you are changing the state inside the effect which then retriggers it so that's expected.
This is a design issue where you need to setup your effect to be more granular and change only the state that it needs to and react to only the state that should trigger a refresh.

Related

Setting state with values inside an object

Im basically trying to set the state with the City value but when I set thee state and console log the state its always empty. Im even console logging along the way.
sample city object from first console.log:
{_id: '625a495ae4bea1099502f824',
City: 'Dakhla Oasis'
Country: 'Egypt'
}
import React from "react";
import { useState } from "react";
export default function Cities() {
const [singlecity, setSingleCity] = useState('');
function GetSingleCity() {
console.log(city)
setSingleCity(city.City);
console.log(singlecity);
}
setState function in react is asynchronous, so if you console.log right after the set state, you will not see the updated value immediately. However if yo try to render the state, you will see the rendered html will be updated. If you want to console.log the latest value of singleCity, you could either move the console.log outside GetSingleCity, so console.log will run on every re-render, or put console.log inside a useEffect:
useEffect(() => {console.log(singleCity)}, [singleCity])
useEffect will run the callback every time the state singleCity has changed, so you will see the updated value

useEffect not getting called on local storage dependency

I tried as following but on change of localstorage useEffect is not getting called.
I have also tried adding dependency localStorage.getItem('quantity') but doesn't work.
import React from 'react';
import Categories from '../molecules/Categories';
import './SideBar.scss';
import { useState, useEffect } from 'react';
const SideBar = () => {
let [quantity, setQuantity] = useState(JSON.parse(localStorage.getItem('quantity')));
useEffect(() => {
console.log("in useEffect");
const onStorage = () => {
setQuantity(JSON.parse(localStorage.getItem('quantity')));
};
window.addEventListener('storage', onStorage);
return () => {
window.removeEventListener('storage', onStorage);
};
}, []);
return (
<div className='sidebar'>
<Categories />
<div>count:{quantity}</div>
</div>
)
}
export default SideBar;
Having an empty dependency array (as in your code above) will ensure that a useEffect runs only once, but I'm not sure why you would need this useEffect to run whenever storage is updated. This useEffect basically just adds an event listener, which does not need to be renewed after every storage update.
It looks like onStorage is what you actually want to run whenever storage is updated, but that is handled by the event listener that the useEffect adds. If you add a console.log inside onStorage, you should see that onStorage is running after every storage update.
Note, too, though, that a storage event will fire only if localStorage is updated by a different window/page; see this MDN article. If the same window is updating localStorage, then to trigger your event handler you will need to dispatch a storage event manually whenever you update the quantity in localStorage:
window.dispatchEvent(new Event('storage'));

Does useState hooks effects performance?

newbie here. I wanted to know that if I use more than 5 useState hook in my react-native app, does it effects my application performance in a bad way?
Like in react, all updates will make a re-render to your app so the fast question is yes.
You need to think about what are you doing for example if you have 2 components to show/hide
This will re-render 2 times
[showA, setShowA] = useState(false);
[showB, setShowB] = useState(false);
onClick = () => {
setShowA(true)
setShowB(true)
}
This will re-render 1 time
[showState, setShowState] = useState({showA: false, showB: false});
onClick = () => {
setShowState((prevState) => {...prevState, showA:true, showB:true})
}

What's wrong with this React Custom Hook?

I've read numerous articles on creating and using Custom Hooks in React but can't figure out why my code is not working.
Here is the heart of the problem code:
cont MyContextProvider = (props) => {
const useCompleteWizard = () => {
// Define `body` object
useEffect(() => {
// const { loading, data } = useFetchPost(`${API_ROOT()}account_management/fleets`, body, app.awsConfig);
useFetchPost(`${API_ROOT()}user_management/users`, body, app.awsConfig);
}, []);
}
}
Within my context provider, I've created the custom hook you see, which in turn calls another custom hook that posts the data.
But I'm getting this error:
React Hook "useFetchPost" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.
I don't see that useFetchPost is being called inside a callback. Which callback? This just doesn't make any sense to me and I'm hoping someone can enlighten me.
Hey you are calling a custom hook inside useEffect callback.you know useEffect take
a callback function.please call your custom hook outside of this effect
please checkout this Invalid Hook Call Warning
https://reactjs.org/warnings/invalid-hook-call-warning.html

react-redux can update child smart components without updating parents?

Imagine the following React structure:
SmartComponentA -> DumbComponentB -> SmartComponentC
Also imagine that SmartComponentA and SmartComponentC each get connected to different slices of the state in their mapStateToProps functions.
Lastly, imagine that we put a console.log in the render method of each of these components.
When I actually try this, on the first render, I see that all components log as expected. But then if I change the data for SmartComponentC, I only see a single log message (C's log message), and I don't see SmartComponentA or DumbComponentB logging anything. How is that possible? How is react-redux getting React to update a child without updating its parents?
I would have assumed that the overriding of shouldComponentUpdate inside of the connect method would mean SmartComponentA would not get re-rendered (since its slice of the state didn't change), and therefore would cause a short-circuiting that would prevent SmartComponentC from getting re-rendered. While connect's implementation is not the same as the pure render mixin, both work by changing shouldComponentUpdate, but the pure render docs clearly state that React will "bail out" (as they put it) if a parent doesn't need to re-render:
for C2's subtree and C7, it didn't even have to compute the virtual DOM as we bailed out on shouldComponentUpdate.
source
If my question still isn't clear, here is sort of pseudo-code for the setup, and I'm asking why I can keep typing in C's input and it only log's C's messages to the console and not A's and B's (why is it not short-circuiting)?
//////////////////////////////////////////////
const SmartComponentA = (props) => {
console.log('rendering SmartComponentA');
return <DumbComponentB bData={props.bData} />;
};
const mapStateToProps = (state) => { bData: state.bData };
export default connect(mapStateToProps)(SmartComponentA);
//////////////////////////////////////////////
const DumbComponentB = (props) => {
console.log('rendering DumbComponentB');
return (
<div>
{props.bData}
<SmartComponentC />
</div>
);
}
export default DumbComponentB;
//////////////////////////////////////////////
const SmartComponentC = (props) => {
console.log('rendering SmartComponentC');
return (
<div>
<input value={props.cValue} onChange={props.changeCValue} />
</div>
);
}
const mapStateToProps = (state) => { cValue: state.cValue };
export default connect(mapStateToProps, { changeCValue })(SmartComponentC);
//////////////////////////////////////////////
On the first render I see all log messages, then if I keep typing in the input, I only see C's log message each time I press a key.
Prop changes trigger the React component lifecycle which will typically trigger the lifecycle of each child component unless -- as you observe, the process can be short-circuited by shouldComponentUpdate.
But prop changes aren't they only thing that triggers the component lifecycle -- state changes do too. And that's how connect function works. The Connect component subscribes to the store and on any store change checks to see if it will update the smart component's props (based on mapStateToProps). If so it will set it's own state triggering the lifecycle functions for the Connect component and it's child.

Resources