react-spectrum icon indicating copy to clipboard operation
react-spectrum copied to clipboard

Export `useSlot` & `useRenderProps`

Open ArrayKnight opened this issue 1 year ago โ€ข 3 comments
trafficstars

Provide a general summary of the feature here

The useSlot & useRenderProps hooks are very useful utilities within the Provider suite. Since we're already able to utilize Provider and the many different component contexts (as well as our own), it would be nice to have full access to related utilities

๐Ÿค” Expected Behavior?

useSlot & useRenderProps are exported by react-aria-components

๐Ÿ˜ฏ Current Behavior

Not currently exported

๐Ÿ’ Possible Solution

No response

๐Ÿ”ฆ Context

I'm currently utilizing useSlot to determine if a slot has been implemented or not, which allows for a flag to be provided for logic / styling branching

I'm expecting to have to implement new custom components that will want to implement their own render props

๐Ÿ’ป Examples

No response

๐Ÿงข Your Company/Team

No response

๐Ÿ•ท Tracking Issue

No response

ArrayKnight avatar Jun 15 '24 17:06 ArrayKnight

At least for useRenderProps we're not too sure about exporting this and making it public. If you need to use it, we suggest that you just copy it for now since it's pretty straightforward.

yihuiliao avatar Jun 17 '24 23:06 yihuiliao

export function callRenderProps<T extends object, R>(
  value: R | ((renderProps: T) => R),
  values: T
) {
  if (typeof value === 'function') {
    return (value as (renderProps: T) => R)(values);
  }

  return value;
}
import { type CSSProperties, type ReactNode, useMemo } from 'react';
import { type RenderProps } from '../../types';
import { callRenderProps } from '../../utils';

type RenderPropsHookOptions<T extends object> = RenderProps<T> & {
  values: T;
  defaultChildren?: ReactNode;
  defaultClassName?: string;
  defaultStyle?: CSSProperties;
};

export function useRenderProps<T extends object>({
  children: childrenProp,
  className: classNameProp,
  style: styleProp,
  defaultChildren,
  defaultClassName,
  defaultStyle,
  values,
}: RenderPropsHookOptions<T>) {
  return useMemo(() => {
    const children =
      callRenderProps(childrenProp, { ...values, defaultChildren }) ??
      defaultChildren;

    const className =
      callRenderProps(classNameProp, { ...values, defaultClassName }) ??
      defaultClassName;

    const style = callRenderProps(styleProp, { ...values, defaultStyle });

    return {
      ...(children != null ? { children } : {}),
      ...(className ? { className } : {}),
      ...(style || defaultStyle ? { style: { ...defaultStyle, ...style } } : {}),
    };
  }, [
    childrenProp,
    classNameProp,
    styleProp,
    defaultChildren,
    defaultClassName,
    defaultStyle,
    values,
  ]);
}

ArrayKnight avatar Jul 02 '24 21:07 ArrayKnight

Why is useContextProps exported but not useRenderProps? Makes no sense...

musjj avatar Oct 19 '24 19:10 musjj

#8013 implements it

raiyansarker avatar Apr 26 '25 22:04 raiyansarker