Created
March 13, 2024 02:41
-
-
Save jamessawyer/4352b8088c0ccbdf63d36fac31604b45 to your computer and use it in GitHub Desktop.
React Patterns
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compound Components using Context | |
type AccordionContextProps = { | |
activeItemIndex: number | |
setActiveItemIndex: (index: number) => void | |
} | |
type AccordionItemProps = { | |
item: { | |
id: number | |
label: string | |
content: string | |
} | |
index: number | |
} | |
const AccordionContext = createContext<AccordionContextProps>({ | |
activeItemIndex: 0, | |
setActiveItemIndex: () => 0 | |
}) | |
const Accordion = ({ children }: { children: ReactNode }) => { | |
const [activeItemIndex, setActiveItemIndex] = useState(0) | |
return ( | |
<AccordionContext.Provider value={{ activeItemIndex, setActiveItemIndex }}> | |
<ul> | |
{children} | |
</ul> | |
</AccordionContext.Provider> | |
) | |
} | |
const AccordionItem = ({ item, index }: AccordionItemProps) => { | |
const { activeItemIndex, setActiveItemIndex } = useContext(AccordionContext) | |
return ( | |
<li onClick={() => setActiveItemIndex(index)} key={item.id}> | |
<strong>{item.label}</strong> | |
{index === activeItemIndex && <p>{item.content}</p>} | |
</li> | |
) | |
} | |
function App() { | |
return ( | |
<> | |
<Accordion> | |
<AccordionItem item={{ id: 1, label: 'item 1', content: 'content 1' }} index={0} /> | |
<AccordionItem item={{ id: 2, label: 'item 2', content: 'content 2' }} index={1} /> | |
<AccordionItem item={{ id: 3, label: 'item 3', content: 'content 3' }} index={2} /> | |
</Accordion> | |
<main> | |
<p>main app here</p> | |
</main> | |
</> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Props Collection with prop getter | |
// 通过组合的方式对传入的属性进行扩展 | |
const compose = (...functions: Function[]) => { | |
return (...args: any[]) => { | |
return functions.forEach(fn => fn?.apply(...args)) | |
} | |
} | |
const getDroppableProps = ({ | |
onDragOver: replacementOnDragOver, | |
...replacementProps | |
}) => { | |
const defaultOnDragOver = (e: Event) => { | |
e.preventDefault() | |
} | |
// 对onDragOver添加一些自定义逻辑 | |
return { | |
onDragOver: compose(replacementOnDragOver, defaultOnDragOver), | |
onDrop: (e: Event) => {}, | |
...replacementProps | |
} | |
} | |
function App() { | |
return ( | |
<> | |
<Dropzone { | |
...getDroppableProps({ | |
onDragOver: () => { | |
alert('Draged!') | |
} | |
}) | |
} | |
/> | |
<main> | |
<p>main app here</p> | |
</main> | |
</> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Render Props Pattern | |
type WindowSizeProps = { | |
render: (size: { width: number, height: number }) => JSX.Element | |
} | |
const WindowSize = (props: WindowSizeProps) => { | |
const [size, setSize] = useState({ width: -1, height: -1 }) | |
useEffect(() => { | |
const handleSize = () => { | |
setSize({ width: window.innerWidth, height: window.innerHeight }) | |
} | |
window.addEventListener('resize', handleSize) | |
return () => { | |
window.removeEventListener('resize', handleSize) | |
} | |
}, []) | |
return props.render(size) | |
} | |
function App() { | |
return ( | |
<> | |
<WindowSize render={({ width, height }) => <div>width: {width}, height: {height}</div>} /> | |
<main> | |
<p>main app here</p> | |
</main> | |
</> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment