Function gets automatically called without changing the useffect value - javascript

Hi I am using redux in react application and I am using redux hooks with functional components.The problem is I want to call this function and dispatch the action only when the value of unmount gets changed.But it's not working as expected it's calling this function automatically.
const checkHasMessages = () => {
recentUSers.map((ci) => {
if (!ci.hasOwnProperty("mesg")) {
dispatch(removeRecentUser(ci.id));
}
});
};
useEffect(() => {
checkHasMessages();
}, [unmount]);

On component mount the state unmout is being set to undefined, thus triggering the useEffect with eh dependency.
You can add an if statement to check the value of unmount.
useEffect(() => {
if(unmount){
checkHasMessages();
}
}, [unmount]);
This should do it (if unmount is initially set to undefined, else u need to create a check based of the value)

Related

Updating a dependency variable after execution of useEffect without triggering that useEffect hook again

As shown in the following react code snippet, I have a useEffect hook with a dependency 'fetchQuery'. The useEffect hook will execute if 'fetchQuery' variable changes. But right after execution of it, I want to clear the value (set to '') of that dependency variable 'fetchQuery' without triggering an infinite loop. Is there a way to do that?
useEffect(() => {
// An async function to fetch some data
getDataModules(fetchQuery);
}, [fetchQuery]);
Since 'fetchQuery' is a state variable and is given as a dependency for this hook, simply clearing its value using setFetchQuery(''); will trigger useEffect again, which I dont want.
Only call the API if fetchQuery exists.
useEffect(() => {
if (fetchQuery) {
getDataModules(fetchQuery);
}
}, [fetchQuery]);
Do setFetchQuery(''); to clear.
const [shouldRefetch, setShouldRefetch] = useState(false);
const [fetchQuery, setFetchQuery] = useState(...);
useEffect(() => {
if (shouldRefetch) {
getDatamodules(fetchQuery);
setShouldRefetch(false);
setFetchQuery('');
}
}, [shouldRefetch]);
const someOtherFunction = () => {
setFetchQuery(...);
SetShouldRefetch(true);
};

Changing a component state prop based on a Onchange of another state prop

I have a state prop that changes based on the input value(amount) the user enters(call it firstState.a). my question is how to change another state prop(fee, secondState.b) based on that value entered. I thought I could conditionally setState of the secondState in a UseEffect by having the firstState.a be the dependency which fires the useEffect whenever it changes. What am I not understanding.
pseudo code
useEffect(()=>{
if(...) {
setSecondState(secondstate.b)
} else {
setSecondState(secondstate.b)
}
}, [firstState.a])
I think this is the way that you need to use it, when the amount changes, the useeffect will be fired and if theres any change in the amount, it will update the fee as well. Or you can also make it work with onChange by setting the second state as well when you update the first state.
useEffect(() => {
setFee(amount)
}, [amount)])
Let's imaging you have 2 different states:
const [stateA, setStateA] = useState('');
const [stateB, setStateB] = useState('');
First effect to run after mounting, let's trigger the stateA change (ideally this is not the case but leave it here for the sake of example - maybe it's coming from an API call, this can be triggered maybe on user's onchange event for example of an input field):
useEffect(() => {
setStateA('value');
}, []);
Second effect will be triggered once stateA changes based on the dependency array and on its value you can call setStateB with the preferred value:
useEffect(() => {
if (stateA === 'value') {
setStateB('first condition applied');
} else {
setStateB('second condition applied');
}
}, [stateA]);
Full example of the function component's body:
const [stateA, setStateA] = useState('');
const [stateB, setStateB] = useState('');
useEffect(() => {
setStateA('value');
}, []);
useEffect(() => {
if (stateA === 'value') {
setStateB('first condition applied');
} else {
setStateB('second condition applied');
}
}, [stateA]);
Good further explanation in the documentation of Using the Effect Hook.

React useState run the useEffect at run-time

I've a function (loadList) in my component to load my list data from API
And at run-time I want to get all data, so I've this code:
useEffect(() => {
loadList();
}, []);
And I've a state (changedFilter) to handle reload list again :
useEffect(() => {
loadList();
}, [changedFilter]);
But after checking the DevTools > Network tab, I've 2 XHR request in this scenario ...
Apparently by default React consider initial values for useState as a change and run the second useEffect with sense on changedFilter state ...
Is any trick to handle it ?
Thanks
useEffect(() => { loadList(); }, [changedFilter]);
will also be trigger on first render as well along with first useEffect therefore your fist useeffect with [] dependency is redundant. Only second useEffect might solve your purpose.
You can avoid the useEffect from running on initial render in 2 ways.
First: Use a ref to track initial render
const initialRender = useRef(true);
useEffect(() => {
if(!initialRender.current) {
loadList();
} else {
initialRender.current = false;
}
}, [changedFilter]);
Second: Check for the existence of changedFilter if its not defined or empty initially
useEffect(() => {
if(changedFilter) { // Change it to changeFilter.length > 0 if its an empty array initially
loadList();
}
}, [changedFilter]);

How can I get the updated state with redux

I have a react project and redux for state management. These are my actions.
const mapDispatchToProps = dispatch => ({
handleChange: (name, value) => { dispatch(handleChange(name, value)) },
filterRooms: (rooms) => { dispatch(filterRooms(rooms)) }
});
I have to use these 2 method one by one.
this.props.handleChange(pets, true); // handle changes
this.filterRooms(); // filtering with changing value
filterRooms = () => {
let {rooms,pets} = this.props; // Here I should get pets === true but it's false.
// filter by pets
if (pets) {
tempRooms = tempRooms.filter(room => room.pets === true);
}
this.props.filterRooms(tempRooms);
}
If I use setTimeout for second method thats ok but I think that's not a correct way.
this.props.handleChange(name, value);
setTimeout(() => {
this.filterRooms();
}, 500);
Seems that below two function run in sequence, one after another
this.props.handleChange(pets, true); // handle changes
this.filterRooms(); // filtering with changing value
First dispatch changed value to Redux. And it is updated there (as sample with setTimeout works). But don't expect updated value from Redux will be immediately available to this.filterRooms().
You have some Reactjs component. Reactjs component is essentially class or function. Then you wrap in in connect. So your code may look like this
class Component1 extends React.Component {
onChange: () => {
this.props.handleChange(pets, true); // handle changes
this.filterRooms(); // filtering with changing value
}
// other staff
}
export default connect(mapStateToProps, mapDispatchToProps)(Component1)
Whats happens in React. It instantiate class Component1, then calls connect which in turn calls some methods of your class (i.e. render() or something else). connect also pass some values from Redux store to your component as props. Method of Component1 is executed and may change Redux state (as it do in your sample). But updated props will not be immediately available. props are just arguments, that have been passed by connect function. To change arguments of any function, you should call it once again. So after receiving updated pets, connect will call your component again with updated pets. But it will be later.
connect() -> calls Component1 and passes props.pets = false -> Compoentn1 sets pets in Redux to true -> connect() receives updated pets and calls Component1 with props.pets = true
That's why trick with setTimeout works. Ste timeout just await for second call of Component1
To solve your exact issue, don't read pets from props if you know that you've updated it.
this.props.handleChange(pets, true); // handle changes
this.filterRooms(true); // filtering with changing value
filterRooms = (pets) => {
let {rooms} = this.props;
// filter by pets
if (pets) {
tempRooms = tempRooms.filter(room => room.pets === true);
}
this.props.filterRooms(tempRooms);
}

state is not updating using React hook

This is a function which has to be called when the component mounts on DOM
const [dashboardData, setDashboardData] = useState('');
const loadDashboardData = () => {
console.log("Loading Dashboard Data ", campaign);
Utils.request({
url: `campaign/user/info`
}).then(
res => {
console.log("dashboard data" , res.data)
setDashboardData(res.data);
},
err => console.log(err)
)
}
useEffect(() => {
loadDashboardData();
console.log("campaigndata",dashboardData);
}, []);
when I console dashboardData in useEffect, it shows nothing but a string i.e campaigndata which I passed as the first argument in console.log. what I think that my dashboard state variable is not getting updated
Answer
Write another useEffect just for dashboardData.
useEffect(() => {
console.log("campaigndata",dashboardData);
}, [dashboardData]);
Explanation
Your useEffect is taking an empty array as the second argument, which makes it run only the first time (as DidMount), so it won't re-run on component re-render after changing the state, that's why it is showing empty string as the initial state.
Writing another useEffect for the variable dashboardData will run as many times as the dashboardData changes.
You can just pass the 'dashboard' to the existing useEffect as dependency. The existing useEffect will work as both componentDidMount and componentDidUpdate.
So no need to write another useEffect.
useEffect(() => {
loadDashboardData();
console.log("campaigndata",dashboardData);
}, [dashboardData]);

Categories

Resources