question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

React hooks question (or bug report?)

See original GitHub issue

Heyyyy team,

How’s everyone doing? šŸ˜„

I was trying out React hooks and was rewriting one of my side project but a buggy issue caught me. I created a repro case here.

The case is:

function App() {
  let store = {};
  const [authStatus, updateAuthStatus] = useState(false);

  useEffect(() => {
    asyncHelper().then(() => {
      store = {
        nested: {
          value: 'Hello World',
        },
      }
      // people will naturally believe store is updated when auth status is true
      // but it's actually not
      updateAuthStatus(true);
    });
  }, []);

  if (!authStatus) {
    return <h1>Loading...</h1>
  }

  return (
    // will throw an error here (store hasn't been updated)
    <h1>{store.nested.value}</h1>
  );
}

I’m casting/updating a new value to store in useEffect, assuming that it works similarly with cDM, and then update the authStatus. But the last line when it tries to render <h1>{store.nested.value}</h1>, it’ll throw the error ā€œcannot read value of undefinedā€ because store hasn’t been updated this time.

It’s very natural to have this operation sequence in mind:

  1. render the loading state
  2. run useEffect
  3. store gets updated
  4. auth status gets updated
  5. render the correct value

However it works as expected if I also wrap the store with a local state:

function App() {
  const [store, updateStore] = useState({});
  const [authStatus, updateAuthStatus] = useState(false);

  useEffect(() => {
    asyncHelper().then(() => {
      updateStore({
        nested: {
          value: 'Hello World',
        },
      })
      
      updateAuthStatus(true);
    });
  }, []);

  if (!authStatus) {
    return <h1>Loading...</h1>
  }

  return (
    // will throw an error here (store hasn't been updated)
    <h1>{store.nested.value}</h1>
  );
}

I’m guessing maybe it’s because the async nature of the state update function but not sure if I missed something here or it’s a bug.

Have fun in React Conf! I’m so excited that we’re finally SHIPPING things! šŸ‘

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
awearycommented, Oct 26, 2018

Yeah, if you want to compare it to class components the equivalent would be doing

render() {
  // Every time the component re-renders, store gets reset
  this.store = {};
2reactions
arianoncommented, Oct 26, 2018

The thing is, a function component’s body is executed every render, while componentDidMount is only executed on mount, so yes, I’d say this is definitely expected behaviour.

It’s not a breaking change because you can still use class components with componentDidMount just fine.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Hooks cheat sheet: Best practices with examples
In this tutorial, we'll outline some React Hooks best practices and highlight some use cases with examples, from simple to advanced scenarios.
Read more >
Invalid Hook Call Warning - React
Invalid Hook Call Warning ... You are probably here because you got the following error message: Hooks can only be called inside the...
Read more >
Avoiding hydration mismatch when using React hooks
Bugs caused by hydration mismatches can be of those type: the website works when you navigate from one page to another, but misbehaves...
Read more >
The Guide to Learning React Hooks (Examples & Tutorials)
Learn all about React Hooks with this hands-on guide. Includes tutorials and code examples on using hooks for state and effects, for context...
Read more >
Making Sense of React Hooks - Medium
Hooks solve exactly that problem. Hooks let you use React features (like state) from a function — by doing a single function call....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found