Reputation: 59
I am trying to pass a variable from the state of a main App component to a component named ShoppingList
as a prop. For some strange reason it is not getting passed even though it is definitely in the state of the of the App component according to React Dev Tools. However, a near identical component named Stocks receives their state variable as a prop and there is seemingly no difference between each one.
const App = () => {
const [stockChange, setStockChange] = useState(false)
const [shoppingListChange, setShoppingListChange] = useState(false)
const [user, setUser] = useState('')
const [loggedIn, setLoggedIn] = useState(false)
const [stocks, setStocks] = useState('')
const [shoppingList, setShoppingList] = useState('')
useEffect(() => {
const loggedInUserJson = window.localStorage.getItem('loggedInUser')
if (loggedInUserJson) {
const userToken = JSON.parse(loggedInUserJson)
setUser(userToken)
setLoggedIn(true)
fetchUserDetails()
} else {
setUser(null)
setLoggedIn(false)
}
}, [loggedIn])
const putShoppingList = async () => {
console.log('put shopping')
return await axios.put(`http://localhost:3001/api/shoppinglists/${shoppingList._id}`, shoppingList,
{
headers: {
'Authorization': `Bearer ${user.token}`
}
})
}
useEffect(() => {
console.log('shopping list change')
putShoppingList()
.then(() => fetchUserDetails())
}, [shoppingListChange])
const fetchUserDetails = async () => {
const res = await axios.get('http://localhost:3001/api/users', {
headers: {
'Authorization': `Bearer ${user.token}`
}
})
setStocks(res.data.stocks)
setShoppingList(res.data.shoppinglists)
}
const putStocks = async () => {
console.log('put stocks')
return await axios.put(`http://localhost:3001/api/stocks/${stocks._id}`, stocks,
{
headers: {
'Authorization': `Bearer ${user.token}`
}
})
}
useEffect(() => {
console.log('stock change')
putStocks()
.then(() => fetchUserDetails())
}, [stockChange])
const logOut = () => {
window.localStorage.removeItem('loggedInUser')
setLoggedIn(false)
}
const getName = () => {
if (user) {
return user.name
} else {
return ''
}
}
return (
<StyledPage>
<Topbar id='topbar' loggedIn={loggedIn} name={getName()} logOut={logOut} />
<Sidebar />
<StyledMain>
<Switch>
<Route path='/login'>
<Login setUser={setUser} setLoggedIn={setLoggedIn} />
</Route>
<Route path='/register' component={Register} />
<Route path='/stock'>
<Stock stocks={stocks} setStocks={setStocks} setStockChange={setStockChange} stockChange={stockChange} />
</Route>
<Route path='/shoppinglist'>
<ShoppingList
shoppingList={shoppingList}
setShoppingList={setShoppingList}
shoppingListChange={shoppingListChange}
setShoppingListChange={setShoppingListChange}
/>
</Route>
</Switch>
</StyledMain>
</StyledPage>
);
}
My only two ideas is that React Router is causing a problem or that the effect hooks are interfering somehow when they are first rendered.
Upvotes: 0
Views: 47
Reputation: 4278
You code has multiple bugs, especially with dependencies and reactions. You should use eslint-plugin-react-hooks
.
const App = () => {
const [stockChange, setStockChange] = useState(false)
const [shoppingListChange, setShoppingListChange] = useState(false)
const [user, setUser] = useState('')
const [loggedIn, setLoggedIn] = useState(false)
const [stocks, setStocks] = useState('')
const [shoppingList, setShoppingList] = useState('')
useEffect(() => {
const loggedInUserJson = window.localStorage.getItem('loggedInUser')
if (loggedInUserJson) {
const userToken = JSON.parse(loggedInUserJson)
setUser(userToken)
setLoggedIn(true)
fetchUserDetails()
} else {
setUser(null)
setLoggedIn(false)
}
}, [])
const putShoppingList = useCallback(async () => {
console.log('put shopping')
return await axios.put(`http://localhost:3001/api/shoppinglists/${shoppingList._id}`, shoppingList,
{
headers: {
'Authorization': `Bearer ${user.token}`
}
})
}, [shoppingList._id, user.token]);
const fetchUserDetails = useCallback(async () => {
const res = await axios.get('http://localhost:3001/api/users', {
headers: {
'Authorization': `Bearer ${user.token}`
}
})
setStocks(res.data.stocks)
setShoppingList(res.data.shoppinglists)
}, [user.token]);
useEffect(() => {
console.log('shopping list change')
putShoppingList()
.then(() => fetchUserDetails())
}, [])
const putStocks = useCallback(async () => {
console.log('put stocks')
return await axios.put(`http://localhost:3001/api/stocks/${stocks._id}`, stocks,
{
headers: {
'Authorization': `Bearer ${user.token}`
}
})
}, [stocks._id, user.token]);
useEffect(() => {
console.log('stock change')
putStocks()
.then(() => fetchUserDetails())
}, [])
const logOut = () => {
window.localStorage.removeItem('loggedInUser')
setLoggedIn(false)
}
const getName = () => {
if (user) {
return user.name
} else {
return ''
}
}
return (
<StyledPage>
<Topbar id='topbar' loggedIn={loggedIn} name={getName()} logOut={logOut}/>
<Sidebar />
<StyledMain>
<Switch>
<Route path='/login'>
<Login setUser={setUser} setLoggedIn={setLoggedIn}/>
</Route>
<Route path='/register' component={Register} />
<Route path='/stock'>
<Stock stocks={stocks} setStocks={setStocks} setStockChange={setStockChange} stockChange={stockChange}/>
</Route>
<Route path='/shoppinglist'>
<ShoppingList
shoppingList={shoppingList}
setShoppingList={setShoppingList}
shoppingListChange={shoppingListChange}
setShoppingListChange={setShoppingListChange}
/>
</Route>
</Switch>
</StyledMain>
</StyledPage>
);
}
Upvotes: 1