Skip to content

Commit

Permalink
Fix useDynamicTextareaHeight initial render with slots (primer#3196)
Browse files Browse the repository at this point in the history
* Fix `useDynamicTextareaHeight` initial render with slots

* Create pink-papayas-relate.md

* Fix lint errors

* chore: run format

---------

Co-authored-by: Josep Martins <josepmartins@github.com>
Co-authored-by: Mike Perrotti <mperrotti@github.com>
Co-authored-by: Josh Black <joshblack@users.noreply.github.com>
Co-authored-by: Josh Black <joshblack@github.com>
  • Loading branch information
5 people committed Jun 20, 2023
1 parent 4a0ea78 commit 21fa73c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-papayas-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": patch
---

Fix `useDynamicTextareaHeight` initial render with slots
13 changes: 11 additions & 2 deletions src/drafts/hooks/useDynamicTextareaHeight.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {RefObject, useLayoutEffect, useState} from 'react'
import {RefObject, useCallback, useEffect, useLayoutEffect, useState} from 'react'

import {SxProp} from '../../sx'
import {getCharacterCoordinates} from '../utils/character-coordinates'
Expand Down Expand Up @@ -34,7 +34,7 @@ export const useDynamicTextareaHeight = ({
const [minHeight, setMinHeight] = useState<string | undefined>(undefined)
const [maxHeight, setMaxHeight] = useState<string | undefined>(undefined)

useLayoutEffect(() => {
const refreshHeight = useCallback(() => {
if (disabled) return

const element = elementRef.current
Expand All @@ -60,8 +60,17 @@ export const useDynamicTextareaHeight = ({
if (minHeightLines !== undefined) setMinHeight(`calc(${minHeightLines} * ${lineHeight})`)
if (maxHeightLines !== undefined) setMaxHeight(`calc(${maxHeightLines} * ${lineHeight})`)
// `value` is an unnecessary dependency but it enables us to recalculate as the user types
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [minHeightLines, maxHeightLines, value, elementRef, disabled])

useLayoutEffect(refreshHeight, [refreshHeight])

// With Slots, initial render of the component is delayed and so the initial layout effect can occur
// before the target element has actually been calculated in the DOM. But if we only use regular effects,
// there will be a visible flash on initial render when not using slots
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(refreshHeight, [])

if (disabled) return {}

return {height, minHeight, maxHeight, boxSizing: 'content-box'}
Expand Down

0 comments on commit 21fa73c

Please sign in to comment.