Skip to content

Instantly share code, notes, and snippets.

@mithi
Last active June 2, 2024 11:33
Show Gist options
  • Save mithi/5c3a24ba62f7c309ccb3ef8988729ece to your computer and use it in GitHub Desktop.
Save mithi/5c3a24ba62f7c309ccb3ef8988729ece to your computer and use it in GitHub Desktop.

See comment below thanks :)

@mithi
Copy link
Author

mithi commented Jun 2, 2024

Hi!

First of all, thank you for taking the time to speak with me during the refactoring session. I learned a lot and really enjoyed the conversation!

I just wanted to share something I learned recently that is quite interesting related to our discussion regarding the useLocalStorage hook. You asked me if there is a way to accomplish the same functionality without using useEffect
and on the fly I couldn't think of any.

Then you proposed the following solution:

const [currency, setCurrency] = React.useState(() => {
    return localStorage.getItem("currency")
})


const updateCurrency = useCallback((newCurrency) => {
    setCurrency(newCurrency)
    localStorage.setItem("currency", newCurrency)
}, [])

I said that that could work and I don't see anything wrong with it. Interestingly enough, today I was reading a section of the react.gg course, and it was almost the same example he brought up in the discussion that this wasn't enough, and we really need to use an useEffect when synchronizing with some outside system such as a localStorage.

Attached are some of the most relevant screenshots of the article including his code.

He brings up two things. One is that it violates two of three simple rules, which "Rule 0: When a component renders, it should do so without running into any side effect" and "Rule 2: If a side effect is synchronizing your component with some external system,
put that side effect inside useEffect".

The discussion for the reasoning behind each rule is quite long, but for rule 0, one of the most important reasons, is that

"When React renders, it does so with the goal of eventually updating the UI. This entire process needs to be as fast as possible.
If it weren't, regardless of the cause, there wouldn't be much value in using React."

and he brings up exactly the lazy initialization of use state and argues:

Now I know what you might be thinking, surely this isn't that big of deal, right? Getting a single item out of local storage is plenty fast. Even if it slightly slows down the initial render, does it really matter? Rebellious of you, but we have rules for a reason.

And talks a little bit about server-side rendering. (See screenshots). I know the app we have is a purely client side app so we don't really care about server-side rendering that much.

But then again, in my personal opinion it wouldn't hurt to just follow the simple rules that is prescribed, by just simply adding around just 3 lines of code. No need to violate any rules, the way we try to never violate the exhaustive deps rule of hooks even though we believe it should be okay not to include functions inside the array of dependencies.

Anyway, just wanted to share this, and hope you check out the screenshots. Thanks :)

Screenshot of the initial implementation which he thinks is not good enough

Screen Shot 2024-06-02 at 6 51 18 PM

Screenshot of where he says lazy initialization in useState by accessing localStorage is not a good idea

Screen Shot 2024-06-02 at 6 46 52 PM

Screenshot of the solution which he prescribes with the use of useEffect

Screen Shot 2024-06-02 at 6 44 35 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment