I am trying to learn React hooks, and trying to convert existing codebase to use hooks, but I am confused.
Is it normal to set state inside useEffect
? Would I be causing the dreaded infinite loop if I do so?
import React, { useState, useEffect } from 'react';
import App from 'next/app';
import Layout from './../components/Layout';
function MyApp({ Component, pageProps }) {
const [ cart, setCart ] = useState([]);
const addToCart = (product) => {
setCart((prevCartState) => {
return [ ...prevCartState, product ];
});
localStorage.setItem('cart', JSON.stringify(cart));
};
//mimicking componentDidMount to run some effect using useEffect
//useEffect(() => setCount((currentCount) => currentCount + 1), []);
useEffect(() => {
const cartCache = JSON.parse(localStorage.getItem('cart'));
//cart = cartCache; Good or bad?
cartCache || setCart(() =>{
});
}, []);
return <Component {...pageProps} />;
}
My original class based component:
/*
export default class MyApp extends App {
state = {
cart: []
}
componentDidMount = () => {
const cart = JSON.parse(localStorage.getItem('cart'));
if (cart) {
this.setState({
cart
});
}
};
addToCart = (product) => {
this.setState({
cart: [...this.state.cart, product]
});
localStorage.setItem('cart', JSON.stringify(this.state.cart));
}
render() {
const { Component, pageProps } = this.props
return (
<contextCart.Provider value={{ cart: this.state.cart, addToCart: this.addToCart }}>
<Layout>
<Component {...pageProps} />
</Layout>
</contextCart.Provider>
)
}
}*/
It's okey to set state inside
useEffect
as long as you don't listen to changes of the same field inside dependency array. In your particular case you are callinguseEffect
only once (since you have passed an empty dependency array).Also would be cool to add the second
useEffect
to listen tocart
changes and keep thelocalStorage
up-to-date.