1

I have the following reactjs code:

import React, { useState, useEffect } from 'react'

const Test = () => {
    const [counter, setCounter] = useState(0)

    useEffect(() => {
        const data = localStorage.getItem('counter')
        setCounter(parseInt(data, 10))
        console.log('init', data)
    }, [])

    useEffect(() => {
        localStorage.setItem('counter', counter)
        console.log('changed', counter)
    }, [counter])

    const addCounter = () => {
        setCounter((c) => c + 1)
        console.log('added', counter)
    }

    return (
        <div>
            {counter}
            <button onClick={addCounter}>+</button>
        </div>
    )
}


function App() {
    return (
        <div className='App'>
            <Test />
        </div>
    )
}

The useEffect() hooks are being called multiple times. The states are persisted in localStorage. But upon page refresh, the states reset to default values:

init 4          <--- counter was incremented to 4 at previous session
changed 0       <-- counter is reset to 0??
init 0          <-- this should not appear
changed 0 

What am I doing wrong?

2
  • 5
    The reason why useEffect() is being called multiple times is probably because you have StrictMode on. Go to your index.js and remove the StrictMode tags. StrictMode renders components multiple times for debugging purposes. Commented Jul 5, 2022 at 18:58
  • 1
    @abnathan bingo! I've removed StrictMode and it's working now. Thanks Commented Jul 5, 2022 at 18:59

1 Answer 1

2

You can use this boilerplate to avoid repeated renders while in <StrictMode>

function App() {

    const [success, setSuccess] = useState(false);

    const isMounted = useRef(false);

    useEffect(() => {
        console.log('started');
        if (isMounted.current) {
            console.log('mounted');
        } else {
            console.log('mounting');
            isMounted.current = true;
        }
    }, [success]);

    const handleClick = (e) => {
        setSuccess(!success);
    }

    return (
        <div className="App">
            <header className="App-header">
                <button className="button" onClick={handleClick}>Action</button>
            </header>
        </div>
    );
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.