Skip to content

Commit 4166efe

Browse files
committed
remove forwarded refs
1 parent 1a9464e commit 4166efe

File tree

15 files changed

+436
-564
lines changed

15 files changed

+436
-564
lines changed

react/advanced-compound-components/01-api-design/lecture/Disclosure.final.jsx

+29-39
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, { useState, useId } from 'react'
33
export function Disclosure({ children, onChange, defaultOpen = false, ...props }) {
44
const [isOpen, setIsOpen] = useState(defaultOpen)
55
const id = useId()
6-
const panelId = `panel-${id}`
6+
const panelId = `${id}-panel`
77

88
children = React.Children.map(children, (child) => {
99
return React.cloneElement(child, {
@@ -23,42 +23,32 @@ export function Disclosure({ children, onChange, defaultOpen = false, ...props }
2323
)
2424
}
2525

26-
export const DisclosureButton = React.forwardRef(
27-
({ children, isOpen, panelId, onSelect, ...props }, forwardedRef) => {
28-
// Note, data attributes in React need to have an empty string in order to be created correctly.
29-
return (
30-
<button
31-
{...props}
32-
onClick={onSelect}
33-
data-disclosure-button=""
34-
data-state={isOpen ? 'open' : 'collapsed'}
35-
aria-expanded={isOpen}
36-
aria-controls={panelId}
37-
ref={forwardedRef}
38-
>
39-
{children}
40-
</button>
41-
)
42-
}
43-
)
44-
45-
DisclosureButton.displayName = 'DisclosureButton'
46-
47-
export const DisclosurePanel = React.forwardRef(
48-
({ children, isOpen, panelId, ...props }, forwardedRef) => {
49-
return (
50-
<div
51-
{...props}
52-
id={panelId}
53-
hidden={!isOpen}
54-
data-disclosure-panel=""
55-
data-state={isOpen ? 'open' : 'collapsed'}
56-
ref={forwardedRef}
57-
>
58-
{children}
59-
</div>
60-
)
61-
}
62-
)
26+
export const DisclosureButton = ({ children, isOpen, panelId, onSelect, ...props }) => {
27+
// Note, data attributes in React need to have an empty string in order to be created correctly.
28+
return (
29+
<button
30+
{...props}
31+
onClick={onSelect}
32+
data-disclosure-button=""
33+
data-state={isOpen ? 'open' : 'collapsed'}
34+
aria-expanded={isOpen}
35+
aria-controls={panelId}
36+
>
37+
{children}
38+
</button>
39+
)
40+
}
6341

64-
DisclosurePanel.displayName = 'DisclosurePanel'
42+
export const DisclosurePanel = ({ children, isOpen, panelId, ...props }) => {
43+
return (
44+
<div
45+
{...props}
46+
id={panelId}
47+
hidden={!isOpen}
48+
data-disclosure-panel=""
49+
data-state={isOpen ? 'open' : 'collapsed'}
50+
>
51+
{children}
52+
</div>
53+
)
54+
}

react/advanced-compound-components/01-api-design/lecture/index.jsx

-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ function App() {
2424
❌ Be able to pass the underlying button own props (like className, id, etc)
2525
unless we do strange API things like `buttonProps={}`
2626
❌ Convert class-names to data-attributes
27-
❌ Be able to forward refs to the panel or button.
28-
❌ Error reporting now refers to the forwarded ref.
29-
- Add a displayName to make it easier to debug.
3027
❌ Add ARIA
3128
- aria-expanded on button
3229
- aria-controls on button

react/advanced-compound-components/02-context-and-events/lecture/Accordion.final.jsx

+52-69
Original file line numberDiff line numberDiff line change
@@ -7,85 +7,74 @@ const AccordionContext = createContext()
77
* Accordion
88
*/
99

10-
export const Accordion = React.forwardRef(
11-
({ children, onChange, defaultIndex = 0, id, ...props }, forwardedRef) => {
12-
const [selectedIndex, setSelectedIndex] = useState(defaultIndex)
13-
const accordionId = useId(id)
14-
15-
// We're mapping over the children (AccordionItem) to get their index. Then we're
16-
// creating a context for each one.
17-
children = React.Children.map(children, (child, index) => {
18-
const panelId = `accordion-${accordionId}-panel-${index}`
19-
const buttonId = `accordion-${accordionId}-button-${index}`
20-
21-
const context = {
22-
buttonId,
23-
panelId,
24-
selected: selectedIndex === index,
25-
selectPanel: () => {
26-
onChange && onChange(index)
27-
setSelectedIndex(index)
28-
},
29-
}
30-
return <AccordionContext value={context} children={child} />
31-
})
32-
33-
function onKeyDown(event) {
34-
event.preventDefault()
35-
const i = selectedIndex
36-
37-
switch (event.key) {
38-
case 'ArrowUp':
39-
if (i !== 0) {
40-
setSelectedIndex(i - 1)
41-
}
42-
break
43-
case 'ArrowDown':
44-
if (i < React.Children.count(children) - 1) {
45-
setSelectedIndex(i + 1)
46-
}
47-
break
48-
default:
49-
break
50-
}
10+
export const Accordion = ({ children, onChange, defaultIndex = 0, id, ...props }) => {
11+
const [selectedIndex, setSelectedIndex] = useState(defaultIndex)
12+
const accordionId = useId(id)
13+
14+
// We're mapping over the children (AccordionItem) to get their index. Then we're
15+
// creating a context for each one.
16+
children = React.Children.map(children, (child, index) => {
17+
const panelId = `accordion-${accordionId}-panel-${index}`
18+
const buttonId = `accordion-${accordionId}-button-${index}`
19+
20+
const context = {
21+
buttonId,
22+
panelId,
23+
selected: selectedIndex === index,
24+
selectPanel: () => {
25+
onChange && onChange(index)
26+
setSelectedIndex(index)
27+
},
28+
}
29+
return <AccordionContext value={context} children={child} />
30+
})
31+
32+
function onKeyDown(event) {
33+
event.preventDefault()
34+
const i = selectedIndex
35+
36+
switch (event.key) {
37+
case 'ArrowUp':
38+
if (i !== 0) {
39+
setSelectedIndex(i - 1)
40+
}
41+
break
42+
case 'ArrowDown':
43+
if (i < React.Children.count(children) - 1) {
44+
setSelectedIndex(i + 1)
45+
}
46+
break
47+
default:
48+
break
5149
}
52-
53-
return (
54-
<div data-accordion="" onKeyDown={onKeyDown} ref={forwardedRef} {...props}>
55-
{children}
56-
</div>
57-
)
5850
}
59-
)
6051

61-
Accordion.displayName = 'Accordion'
52+
return (
53+
<div data-accordion="" onKeyDown={onKeyDown} {...props}>
54+
{children}
55+
</div>
56+
)
57+
}
6258

6359
/**
6460
* Accordion Item
6561
*/
6662

67-
export const AccordionItem = React.forwardRef(({ children, ...props }, forwardedRef) => {
63+
export const AccordionItem = ({ children, ...props }) => {
6864
const { selected } = use(AccordionContext)
6965

7066
return (
71-
<div
72-
{...props}
73-
data-accordion-item=""
74-
data-state={selected ? 'open' : 'collapsed'}
75-
ref={forwardedRef}
76-
>
67+
<div {...props} data-accordion-item="" data-state={selected ? 'open' : 'collapsed'}>
7768
{children}
7869
</div>
7970
)
80-
})
81-
82-
AccordionItem.displayName = 'AccordionItem'
71+
}
8372

8473
/**
8574
* Accordion Button
8675
*/
8776

88-
export const AccordionButton = React.forwardRef(({ children, onClick, ...props }, forwardedRef) => {
77+
export const AccordionButton = ({ children, onClick, ...props }) => {
8978
const { buttonId, panelId, selected, selectPanel } = use(AccordionContext)
9079

9180
return (
@@ -97,20 +86,17 @@ export const AccordionButton = React.forwardRef(({ children, onClick, ...props }
9786
aria-expanded={selected}
9887
id={buttonId}
9988
aria-controls={panelId}
100-
ref={forwardedRef}
10189
>
10290
{children}
10391
</button>
10492
)
105-
})
106-
107-
AccordionButton.displayName = 'AccordionButton'
93+
}
10894

10995
/**
11096
* Accordion Panel
11197
*/
11298

113-
export const AccordionPanel = React.forwardRef(({ children, ...props }, forwardedRef) => {
99+
export const AccordionPanel = ({ children, ...props }) => {
114100
const { buttonId, panelId, selected } = use(AccordionContext)
115101

116102
return (
@@ -122,11 +108,8 @@ export const AccordionPanel = React.forwardRef(({ children, ...props }, forwarde
122108
hidden={!selected}
123109
data-accordion-panel=""
124110
data-state={selected ? 'open' : 'collapsed'}
125-
ref={forwardedRef}
126111
>
127112
{children}
128113
</div>
129114
)
130-
})
131-
132-
AccordionPanel.displayName = 'AccordionPanel'
115+
}

0 commit comments

Comments
 (0)