Ink: `Box` `height` doesn't reset on re-render

Created on 16 Sep 2019  路  7Comments  路  Source: vadimdemedes/ink

It appears that the height property might be updated when re-rendering a component, though I may be misunderstanding something!

Here's a quick example:

// We're waiting for an async process, so we'll want a loading state.
const [results, setResults] = useState([])
useEffect(() => {
  loadResults().then(output => {
    setResults(output)
  })
}, [])

// Loading state if we're still waiting on the results
if (results.length === 0) {
  return (
    <Box height={3}>
      <Color grey>Loading...</Color>
    </Box>
  )
}

// Once the results load, show the list:
return (
  <Box flexDirection="column">
    <Color>1</Color>
    <Color>2</Color>
    <Color>3</Color>
    <Color>4</Color>
    <Color>5</Color>
  </Box>
)

I would expect to see all five numbers printed out, but only see the first three:

$ yarn dev
1
2
3

When run with debug=true:

PS -- would be nice if debug mode added in a newline in between renders!

$ yarn dev --debug
Loading...

1
2
31
2

Note: I just swapped height out with marginTop/marginBottom here and it works fine!

bug

Most helpful comment

I can't believe I just spent an entire day debugging React internals and all it was is just out-dated react-reconciler dependency that I had. Kill me now.

All 7 comments

Could you try out https://github.com/vadimdemedes/ink/pull/232 and let me know if it fixes the issue for you?

Put this example in colinking/ink-testing, so it can be run like so:

$ git checkout https://github.com/colinking/ink-testing.git
$ npm i
$ npx ts-node src/height.tsx

Just tried running it with the latest version from your branch, and it appears that the CLI exits without waiting. For example:

// "ink": "^2.3.0",
$ npx ts-node src/height.tsx
1
2
3

$ 
// "ink": "vadimdemedes/ink#experimental-reconciler",
$ npx ts-node src/height.tsx
Loading...


$ 

Yeah, I had the exact same problem few days ago. Replacing useEffect with useLayoutEffect has solved it for me. Check out https://github.com/vadimdemedes/ink/pull/147#issuecomment-531598933. TLDR is useEffect doesn't run soon enough after Ink renders a frame, so process exits before setTimeout is executed in your code. useLayoutEffect however, ensures to run the effect immediately after render.

I'm not sure why original reconciler/renderer doesn't have the same problem, I wonder if it's the slowness of building new output every frame. New reconciler is significantly faster in that regard, so it could be that.

I can't believe I just spent an entire day debugging React internals and all it was is just out-dated react-reconciler dependency that I had. Kill me now.

Fixed via https://github.com/vadimdemedes/ink/commit/e5b7569c2e6b65624e60ef68b7a06c3db1a0ed01 for non-experimental mode. Will keep this issue open until release.

Fixed in 2.5.0.

Was this page helpful?
0 / 5 - 0 ratings