Skip to content

Commit

Permalink
feat: [FX-377] Proxy ref from forwardRef to FileInput (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
denieler authored and Milos Mosovsky committed Aug 23, 2019
1 parent f29c842 commit bebea62
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
14 changes: 9 additions & 5 deletions src/components/FileInput/FileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Loader from '../Loader'
import Link from '../Link'
import Typography from '../Typography'
import { Check16, UploadDocument16 } from '../Icon'
import { isNumber, isBoolean } from '../utils'
import { isNumber, isBoolean, useCombinedRefs } from '../utils'
import styles from './styles'

export interface FileInfo {
Expand Down Expand Up @@ -106,7 +106,12 @@ export const FileInput = forwardRef<HTMLInputElement, Props>(function FileInput(
},
ref
) {
const nativeInput = useRef<HTMLInputElement>()
// if `ref` is null then we need a ref to control the input
// so we create another ref manually if needed and merge both of them
const inputRef = useCombinedRefs<HTMLInputElement>(
ref,
useRef<HTMLInputElement>(null)
)

const inProgress =
(isNumber(progress) && progress! <= 100) ||
Expand Down Expand Up @@ -146,7 +151,7 @@ export const FileInput = forwardRef<HTMLInputElement, Props>(function FileInput(
size='small'
variant={uploadButtonVariant}
disabled={disabled}
onClick={() => nativeInput.current && nativeInput.current.click()}
onClick={() => inputRef.current && inputRef.current.click()}
>
{uploadButtonTitle}
</Button>
Expand All @@ -156,7 +161,7 @@ export const FileInput = forwardRef<HTMLInputElement, Props>(function FileInput(

return (
<OutlinedInput
ref={ref}
ref={inputRef}
className={className}
style={style}
classes={{
Expand All @@ -182,7 +187,6 @@ export const FileInput = forwardRef<HTMLInputElement, Props>(function FileInput(
accept,
status
}}
inputRef={nativeInput}
startAdornment={startAdornment}
endAdornment={endAdornment}
/>
Expand Down
5 changes: 1 addition & 4 deletions src/components/OutlinedInput/OutlinedInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export interface Props
disabled?: boolean
inputComponent?: ReactType<InputBaseComponentProps>
inputProps?: InputBaseComponentProps
inputRef?: React.Ref<any> | React.RefObject<any>
value?: ValueType
/** Whether `Input` should be rendered as `TextArea` or not */
multiline?: boolean
Expand Down Expand Up @@ -74,7 +73,6 @@ const OutlinedInput = forwardRef<HTMLInputElement, Props>(
disabled,
inputComponent,
inputProps,
inputRef,
value,
type,
error,
Expand All @@ -89,7 +87,6 @@ const OutlinedInput = forwardRef<HTMLInputElement, Props>(
<MUIOutlinedInput
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
ref={ref}
classes={{
root: cx(classes.root, classes[`root${capitalize(width!)}`]),
input: classes.input,
Expand All @@ -103,7 +100,7 @@ const OutlinedInput = forwardRef<HTMLInputElement, Props>(
error={error}
inputComponent={inputComponent}
inputProps={inputProps}
inputRef={inputRef}
inputRef={ref}
value={value}
type={type}
startAdornment={startAdornment}
Expand Down
2 changes: 2 additions & 0 deletions src/components/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export { default as isBoolean } from './is-boolean'
export { default as isSubstring } from './is-substring'
export { Maybe } from './monads'
export { useNotifications } from './Notifications'

export { default as useCombinedRefs } from './use-combined-refs'
24 changes: 24 additions & 0 deletions src/components/utils/use-combined-refs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { RefObject, Ref, useRef, useEffect } from 'react'

const useCombinedRefs = <T>(...refs: (RefObject<T> | Ref<T>)[]) => {
const targetRef = useRef<T>(null)

useEffect(() => {
refs.forEach(ref => {
if (!ref) {
return
}

if (typeof ref === 'function') {
ref(targetRef.current)
} else {
// @ts-ignore
ref.current = targetRef.current
}
})
}, [refs])

return targetRef
}

export default useCombinedRefs

0 comments on commit bebea62

Please sign in to comment.