Dealing with refs in function component without forwardRef

2k views Asked by At

I'm having a situation with refs and simply looking for a workaround.

https://github.com/styleguidist/react-docgen-typescript/issues/314

Using a utility method that is essentially React.forwardRef under the hood is breaking the automatic type documentation in my Storybook.

I don't mind temporarily exporting 2 components:

  1. One without forwardRef for Storybook
  2. One with forwardRefWithAs for application usage

However, this obviously doesn't just... "work" because of refs not passing implicitly in normal functions.

Is something like this viable? Are there any gotchas with it?

// i'll use a generic
const useForwardedRef = (ref: React.Ref<any>) =>{
  const innerRef = useRef<any>(null);
  useEffect(() => {
    if (!ref) return;
    if (typeof ref === 'function') {
      ref(innerRef.current);
    } else {
      ref.current = innerRef.current;
    }
  });
 
  return innerRef;
}

I could also just do:

export const ButtonWithoutForwardRefWithAs = forwardRef((props: ButtonProps, ref: React.Ref<any>) => <JSX {...props} ref={ref} />

const Button = forwardRefWithAs<NonSemanticButtonProps, 'button'>((props: ButtonProps, ref) => (
  <ButtonWithoutForwardRefWithAs {...props} ref={ref} />
));

What do you think?

1

There are 1 answers

0
Kyle Holmberg On

This ended up having nothing to do with the utility method. Instead, it had to do with how I was exporting things.

Previously:

const Button = forwardRefWithAs<NonSemanticButtonProps, 'button'>((props: ButtonProps, ref) => (
  <ButtonWithoutForwardRefWithAs {...props} ref={ref} />
));

Button.displayName = 'Button';

export { Button };

Working:

export const Button = forwardRefWithAs<NonSemanticButtonProps, 'button'>((props: ButtonProps, ref) => (
  <ButtonWithoutForwardRefWithAs {...props} ref={ref} />
));

Button.displayName = 'Button';