useSlottedContext should not throw when slot is not found
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 9m
- Merged PRs (30d)
- 59
Description
### Provide a general summary of the issue here
Referring to this code:
```ts
if (!ctx.slots[slotKey]) {
let availableSlots = new Intl.ListFormat().format(Object.keys(ctx.slots).map(p => `"${p}"`));
let errorMessage = slot ? `Invalid slot "${slot}".` : 'A slot prop is required.';
throw new Error(`${errorMessage} Valid slot names are ${availableSlots}.`);
}
```
https://github.com/adobe/react-spectrum/blob/main/packages/react-aria-components/src/utils.tsx#L171-L176
This violates Open/Close principle, so that it hinders the ability to compose and add new slots in extended components.
Using `Button` as example, I want to add a `clear` slot and use the button to clear the text in a input field:
```tsx
```
```tsx
export function ClearButton() {
return X
}
```
```tsx
export const StyledButtonContext = createContext>(null)
export const StyledButton = forwardRef(props, ref) {
;[props, ref] = useContextProps(props, ref, ButtonContext]
;[props, ref] = useContextProps(props, ref, StyledButtonContext]
return
}
```
```tsx
export function InputField({ children }) {
return (
{children}
)
}
```
Since the props `{ slot: 'clear' }` is eventually passed to `useSlottedContext`, it throws.
Workaround this requires manually picking out `slot: 'clear'` in the `StyledButton`, breaking encapsulation and OCP.
Something like:
```tsx
export const StyledButton = forwardRef(props, ref) {
const { slot, ...rest } = props
let baseButtonProps = slot === 'clear' ? rest : props
;[props, ref] = useContextProps(baseButtonProps, ref, ButtonContext]
;[props, ref] = useContextProps({ slot, ...props}, ref, StyledButtonContext]
baseButtonProps = slot === 'clear' ? rest : props
return
}
```
You can see this is not scalable as more slots are used in the system.
### 🤔 Expected Behavior?
return `undefined`
### 😯 Current Behavior
throw error
### 💁 Possible Solution
_No response_
### 🔦 Context
See above
### 🖥️ Steps to Reproduce
Hopefully the example above should be clear enough.
### Version
1.13.0
### What browsers are you seeing the problem on?
Chrome
### If other, please specify.
_No response_
### What operating system are you using?
macos
### 🧢 Your Company/Team
Palo Alto Networks
### 🕷 Tracking Issue
_No response_
Contributor guide
Research direction
Start in packages/react-aria-components/src/utils.tsx at useSlottedContext, especially the logic around lines 171–176, and trace it through the Button and context composition shown in the issue. Done means a missing clear slot no longer throws and the example can pass slot="clear"; run the relevant package tests to verify the behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100