The reason for the experienced behavior is not that useEffect isn't working. It's because of the way function components work.
If you look at your child component, if useEffect is executed and the component rerenders, defaultValues would be set to 0 again, because the code inside of the function is executed on each render cycle.
To work around that, you would need to use the useState to keep your local state consistent across renders.
This would look something like this:
function EditKat({ aa }) {
// Data stored in useState is kept across render cycles
let [defaultValues, setDefaultValues] = useState(0)
useEffect(() => {
setDefaultValues(2) // setDefaultValues will trigger a re-render
}, [aa])
console.log(defaultValues)
}
Answer from Linschlager on Stack OverflowThe reason for the experienced behavior is not that useEffect isn't working. It's because of the way function components work.
If you look at your child component, if useEffect is executed and the component rerenders, defaultValues would be set to 0 again, because the code inside of the function is executed on each render cycle.
To work around that, you would need to use the useState to keep your local state consistent across renders.
This would look something like this:
function EditKat({ aa }) {
// Data stored in useState is kept across render cycles
let [defaultValues, setDefaultValues] = useState(0)
useEffect(() => {
setDefaultValues(2) // setDefaultValues will trigger a re-render
}, [aa])
console.log(defaultValues)
}
I faced the same problem, I debugged it and i found that, i am mutating the state directly instead of cloning it and using it. So, that's why useEffect is not triggered.
My useEffect in Context.js is not triggering at all. I am trying update state within it
Bug: useEffect not firing when depending on hook value
React useEffect doesn't trigger sometimes when I update my list as its dependency
How to fix the issue of UseEffect not triggering on route change even after feeding in Params Object's property as dependency?
I am trying to setState inside useEffect but the useEffect is not getting triggered at all
import React, { useEffect, useState } from 'react'
import items from './data'
const RoomContext = React.createContext();
const RoomProvider = ({children}) => {
const [state, setState] = useState({
rooms: [],
sortedRooms: [],
featuredRooms: [],
loading: true,
})
const formatData =(items) => {
let tempItems = items.map((item)=> {
let id = item.sys.id;
let images = item.fields.images.map(image => image.fields.file.url);
let room= {...item.fields, images,id};
return room;
});
return tempItems;
}
useEffect(()=> {
console.log(items)
let rooms= formatData(items);
console.log(rooms)
let featuredRooms = rooms.filter(room => room.featured === true)
console.log("aaaaaaa",featuredRooms)
setState({
rooms,
sortedRooms: rooms,
featuredRooms,
loading: false
})
console.log("render")
},[state])
console.log("dying")
return (
<RoomContext.Provider value={{state,setState}}>
{children}
</RoomContext.Provider>
)
}
const RoomConsumer = RoomContext.Consumer;
export { RoomContext, RoomProvider, RoomConsumer };The array that you're creating isn't being stored in state, so every render a new array is being created. The solution is to use react state:
function MyComponent() {
const [myList, setMyList] = useState([0,1,2,3,4])
useEffect(() => {
console.log(myList)
}, [myList])
return (
<div>
{JSON.stringify(myList)}
<button onClick={() => setMyList([...myList, myList.length])}>Add</button>
</div>);
}
I couldn't make a comment on @Gerard's answer until I have more reputation points. I want to add that make sure you pass an arrow function to setMyList as shown:
function MyComponent() {
const [myList, setMyList] = useState([0,1,2,3,4])
useEffect(() => {
console.log(myList)
}, [myList])
return (
<div>
{JSON.stringify(myList)}
<button onClick={() => setMyList(prevList => [...prevList, prevList.length])}>Add</button>
</div>);
}
Here's my App.js component
App.js
function App() {
return (
<GithubProvider>
<AlertProvider>
<Router>
<div className="flex flex-col justify-between h-screen">
<Navbar />
<main className='container mx-auto px-3 pb-12'>
<Alert />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:login" element={<User />} /> {/* ISSUE */}
<Route path="*" element={<NotFound />} />
</Routes>
</main>
<Footer />
</div>
</Router>
</AlertProvider>
</GithubProvider>
);
}The route change to the user component happens in Home Component, I search for a github profile,
a lift of profiles are displayed, I click on the visit profile button on the profile card, which Links me to User component
UserItem.js:
import { Link } from 'react-router-dom'
import PropTypes from 'prop-types'
const UserItem = ({user: {login, avatar_url}}) => {
return (
<div className='card shadow-md compact side bg-base-600'>
<div className='flex-row items-center space-x-4 card-body'>
<div>
<div className='avatar'>
<div className='rounded-full shadow w-14 h-14'>
<img src={avatar_url} alt='Profile' />
</div>
</div>
</div>
<div>
<h2 className='card-title'>{login}</h2>
<Link
className='text-base-content text-opacity-60'
to={`/user/${login}`}
>
Visit Profile {/* TRIGGERING HERE!!!!!!!!!!! */}
</Link>
</div>
</div>
</div>
)
}
UserItem.propTypes = {
user: PropTypes.object.isRequired,
}
export default UserItem;My user Component where the function getUser needs to be triggered->
The function getUsers works fine as when i used it outside an useEffect, it did give me the right response from the fetch call inside.
User.js
import React, { useEffect, useContext } from 'react'
import {FaCodepen, FaStore, FaUserFriends, FaUsers} from 'react-icons/fa'
import { Link } from 'react-router-dom'
import GithubContext from '../context/github/GithubContext'
import { useParams } from 'react-router-dom'
import Spinner from '../components/layout/Spinner'
import RepoList from '../components/repos/RepoList'
export const User = () => {
const params = useParams()
const { getUser, user, loading, getUserRepos, repos } =
useContext(GithubContext)
console.log("params", params, "login", params.login) // WORKS FINE
useEffect ( () => {
console.log("use-effect", getUser, "", params.login)
getUser(params.login)
getUserRepos(params.login)
},[params.login]) // DOESNT TRIGGER WITH [] or [params.login]
console.log( "user-check",user) // user object empty
const {
name,
type,
avatar_url,
location,
bio,
blog,
twitter_username,
login,
html_url,
followers,
following,
public_repos,
public_gists,
hireable,
} = user
console.log("YES THIS PAGE") // Here I was checking whether page is being mounted and YES it is being mounted
const websiteUrl = blog?.startsWith('http') ? blog : 'https://' + blog
if(loading){
return <Spinner />
}
return (<> TYPICAL INFORMATION DISPLAY UI </>)
}Hello,
I have a functional object which has three variables managed by the useState hook. These are categories, activeCategories and shownGames. For now I need something simple - run a function when categories update. I am using useEffect hook but it doesn't seem to work.
This is the code for the needed parts - https://pastie.io/uyakqz.js
I use JSON.stringify to check for the category updates (found that solution on StackOverflow). The issue is that the function specified in the useEffect hook doesn't run (it only runs when I load my page). Any help is appreciated!
So I have this code:
import { useEffect, useState } from "react";
function useCounter(arr = [1, 2, 3, 4, 5]) {
console.log("useCounter");
const [counter, setCount] = useState(0);
useEffect(() => {
console.log("Effect");
for (const i of arr) {
setCount(i);
console.log(counter);
}
}, [arr]);
}
function App() {
console.log("____________________________________");
useCounter();
console.log("App");
return <div className="App" />;
}
export default App;It outputs this:
____________________________________ useCounter App Effect 0 (5 times) ____________________________________ useCounter App Effect 5 (5 times) ____________________________________ useCounter App
Stuff going on with the first 2 rerenders is pretty straightforward and explainable (if not I will write it in a comment or edit this post writing my interpretation of what's going on) but what I couldn't wrap my head around is what's going on on the 3rd rerender.
So "useCounter" is getting logged because useCounter hook is being called then App is logged because it goes next (useEffect's callback is getting called right after the component renders something, so in this case it goes at the end), but useEffect's callback is not getting called even tho it's dependency (arr) was reestablished when useCounter was called and arr argument was assigned with a new instance of array [1,2,3,4,5] so it's a new array which is passed as a dependency to useEffect so it should run again right? causing an infinite loop of rerenders, but it doesn't, why is that happening? I have a guess that it somehow realizes that the previous counter and current counter gonna end up the same so no state changes and thus there is no point running useEffect's callback anymore despite dependency change but how is that happening without running the callback?
That question doesn't make me rest maybe react community could help me, please bring me peace at last