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.

Bailouts for state updates behavior inconsistently for hooks

See original GitHub issue

This is a bug I think.

As the title says, React didn’t help me to merge the update requests.

const Player = ({ }) => {
  const [name, setName] = useState('John Higgins',)
  const [age, setAge] = useState(47)
  const nextPlayer = () => {
    setName('Mark Selby')
    setAge(34)
  }
  console.log('render.')
  return <p>
    This player's name is {name}, {age} years.
    <button type="button" onClick={nextPlayer}>next</button>
  </p>
}

After the button clicked, it outputs:

>> render.
>> render.

But in fact, I got three.

>> render.
>> render.
>> render.

It doesn’t always be.

The actual code

const List = ({}) => {
	const [items, setItems] = useState<ListItem[]>([])
	const [tick, setTick] = useState(0)
	const [page, setPage] = useState(1)
        
        // # effect 001
	useEffect(() => {
           const refresh = tick > 1
           load({ refresh, page })
             .then(d => {
                if (refresh) setItems(d) // replace
                else setItems([...items, ...d]) // append
             })
        }, [tick, page])

        // # effect 002
        useEffect(() => {
            testingScrollToBottom(() => {
               setTick(0) // makes effect 001 applied.
               setPage(page + 1) // makes effect 001 applied again.
            })
            return () => {
                stopTestingScrollToBottom()
            }
        }, [page])
        
        return (
            <div>
                <button
                    onClick={() => {
                        setTick(tick + 1)
                        setPage(1)
                    }}>
                    Refresh
                </button>
                { items.map(item => <Item item={item}/>) }
            </div>
        )
}

Function testingScrollToBottom is where the things happened.

Here is what I did to avoid that:

image

By the way, testingScrollToBottom uses setTimeout.

Issue Analytics

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

github_iconTop GitHub Comments

1reaction
amitnovickcommented, Nov 15, 2019

Just suffered from this issue, and am glad to see it’s already been reported and has been discussed.

Minimal Reproduction

Wanted to offer a minimal reproduction for anyone coming here trying to understand the issue, with setTimeout calling setter functions returned by useState hook, and React not merging (batching) those updates:

function App() {
  const [first, setFirst] = React.useState();
  const [second, setSecond] = React.useState();
  const [third, setThird] = React.useState();

  console.log("render: first:", first, "second:", second, "third:", third);

  return (
    <button
      onClick={() => {
        setTimeout(() => {
          setFirst(1);
          setSecond(2);
          setThird(3);
        }, 1000);
      }}
    >
      Click me!
    </button>
  );
}

/* Console output on click: */
// render: first: 1 second: undefined third:  undefined
// render: first: 1 second: 2 third: undefined
// render: first: 1 second: 2 third:  3

Basically, clicking the button will trigger 3 renderings of the component (one for each setState function called from within setTimeout), each rendering with only a partial state update.

CodeSandbox: https://codesandbox.io/s/unexpected-renderings-with-incomplete-state-update-txhy7

1reaction
bvaughncommented, Oct 15, 2019

React’s event batching does take things like this into consideration, but we wouldn’t want React to be in the business of overriding global/native APIs like setTimeout.

FWIW the upcoming concurrent mode will automatically batch nearby state updates, like in the case you shared, so this wouldn’t have been an issue either.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Could a Federal Loan Program Help Fix Ailing State Public ...
We have argued that a federal bailout of state pension plans is a bad idea for numerous reasons. But the calls for doing...
Read more >
the arbitrary and inconsistent non-bank sifi designation ...
Yet, FSOC additionally fails to conduct any cost-benefit analysis when designating a firm as a SIFI. For this reason, the Oversight and ...
Read more >
Treatment of Certain Interests in Corporations as Stock or ...
Congress added section 385(c) in response to issuers and holders characterizing a corporate instrument inconsistently. H.R. Rep. No.
Read more >
Bug listing with status CONFIRMED as at 2022/12/26 10:46:31
status:CONFIRMED resolution: severity:enhancement · Bug:21509 - "[PATCH] [IDEA] ... Bug:45276 - "Req: ebuild for state threads" status:CONFIRMED resolution: ...
Read more >
Change log : linux-aws-5.11 package : Ubuntu
MX8QXP" - net/mlx4_en: Update reported link modes for 1/10G - ALSA: hda: Add ... state in bringup_cpu() - f2fs: set SBI_NEED_FSCK flag when...
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