RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/AGENTS.md/itxSaaad/medlens-plus-app

AGENTS.md

.cursor/skills/web-frontend/references/composition-patterns/AGENTS.md
AGENTS.md

Quality

45/100

Scores the file, not the repository.

Length

2,507 words

16 headings · 28 code blocks

Repository

0

— · pushed 1 days ago

Last changed

3 days ago

First indexed 3 days ago.
itxSaaad/medlens-plus-app/.cursor/skills/web-frontend/references/composition-patterns/AGENTS.mdRawGitHub
1# React Composition Patterns
2 
3**Version 1.0.0**
4Engineering
5January 2026
6 
7> **Note:**
8> This document is mainly for agents and LLMs to follow when maintaining,
9> generating, or refactoring React codebases using composition. Humans
10> may also find it useful, but guidance here is optimized for automation
11> and consistency by AI-assisted workflows.
12 
13---
14 
15## Abstract
16 
17Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale.
18 
19---
20 
21## Table of Contents
22 
231. [Component Architecture](#1-component-architecture) — **HIGH**
24 - 1.1 [Avoid Boolean Prop Proliferation](#11-avoid-boolean-prop-proliferation)
25 - 1.2 [Use Compound Components](#12-use-compound-components)
262. [State Management](#2-state-management) — **MEDIUM**
27 - 2.1 [Decouple State Management from UI](#21-decouple-state-management-from-ui)
28 - 2.2 [Define Generic Context Interfaces for Dependency Injection](#22-define-generic-context-interfaces-for-dependency-injection)
29 - 2.3 [Lift State into Provider Components](#23-lift-state-into-provider-components)
303. [Implementation Patterns](#3-implementation-patterns) — **MEDIUM**
31 - 3.1 [Create Explicit Component Variants](#31-create-explicit-component-variants)
32 - 3.2 [Prefer Composing Children Over Render Props](#32-prefer-composing-children-over-render-props)
334. [React 19 APIs](#4-react-19-apis) — **MEDIUM**
34 - 4.1 [React 19 API Changes](#41-react-19-api-changes)
35 
36---
37 
38## 1. Component Architecture
39 
40**Impact: HIGH**
41 
42Fundamental patterns for structuring components to avoid prop
43proliferation and enable flexible composition.
44 
45### 1.1 Avoid Boolean Prop Proliferation
46 
47**Impact: CRITICAL (prevents unmaintainable component variants)**
48 
49Don't add boolean props like `isThread`, `isEditing`, `isDMThread` to customize
50 
51component behavior. Each boolean doubles possible states and creates
52 
53unmaintainable conditional logic. Use composition instead.
54 
55**Incorrect: boolean props create exponential complexity**
56 
57```tsx
58function Composer({
59 onSubmit,
60 isThread,
61 channelId,
62 isDMThread,
63 dmId,
64 isEditing,
65 isForwarding,
66}: Props) {
67 return (
68 <form>
69 <Header />
70 <Input />
71 {isDMThread ? (
72 <AlsoSendToDMField id={dmId} />
73 ) : isThread ? (
74 <AlsoSendToChannelField id={channelId} />
75 ) : null}
76 {isEditing ? (
77 <EditActions />
78 ) : isForwarding ? (
79 <ForwardActions />
80 ) : (
81 <DefaultActions />
82 )}
83 <Footer onSubmit={onSubmit} />
84 </form>
85 )
86}
87```
88 
89**Correct: composition eliminates conditionals**
90 
91```tsx
92// Channel composer
93function ChannelComposer() {
94 return (
95 <Composer.Frame>
96 <Composer.Header />
97 <Composer.Input />
98 <Composer.Footer>
99 <Composer.Attachments />
100 <Composer.Formatting />
101 <Composer.Emojis />
102 <Composer.Submit />
103 </Composer.Footer>
104 </Composer.Frame>
105 )
106}
107 
108// Thread composer - adds "also send to channel" field
109function ThreadComposer({ channelId }: { channelId: string }) {
110 return (
111 <Composer.Frame>
112 <Composer.Header />
113 <Composer.Input />
114 <AlsoSendToChannelField id={channelId} />
115 <Composer.Footer>
116 <Composer.Formatting />
117 <Composer.Emojis />
118 <Composer.Submit />
119 </Composer.Footer>
120 </Composer.Frame>
121 )
122}
123 
124// Edit composer - different footer actions
125function EditComposer() {
126 return (
127 <Composer.Frame>
128 <Composer.Input />
129 <Composer.Footer>
130 <Composer.Formatting />
131 <Composer.Emojis />
132 <Composer.CancelEdit />
133 <Composer.SaveEdit />
134 </Composer.Footer>
135 </Composer.Frame>
136 )
137}
138```
139 
140Each variant is explicit about what it renders. We can share internals without
141 
142sharing a single monolithic parent.
143 
144### 1.2 Use Compound Components
145 
146**Impact: HIGH (enables flexible composition without prop drilling)**
147 
148Structure complex components as compound components with a shared context. Each
149 
150subcomponent accesses shared state via context, not props. Consumers compose the
151 
152pieces they need.
153 
154**Incorrect: monolithic component with render props**
155 
156```tsx
157function Composer({
158 renderHeader,
159 renderFooter,
160 renderActions,
161 showAttachments,
162 showFormatting,
163 showEmojis,
164}: Props) {
165 return (
166 <form>
167 {renderHeader?.()}
168 <Input />
169 {showAttachments && <Attachments />}
170 {renderFooter ? (
171 renderFooter()
172 ) : (
173 <Footer>
174 {showFormatting && <Formatting />}
175 {showEmojis && <Emojis />}
176 {renderActions?.()}
177 </Footer>
178 )}
179 </form>
180 )
181}
182```
183 
184**Correct: compound components with shared context**
185 
186```tsx
187const ComposerContext = createContext<ComposerContextValue | null>(null)
188 
189function ComposerProvider({ children, state, actions, meta }: ProviderProps) {
190 return (
191 <ComposerContext value={{ state, actions, meta }}>
192 {children}
193 </ComposerContext>
194 )
195}
196 
197function ComposerFrame({ children }: { children: React.ReactNode }) {
198 return <form>{children}</form>
199}
200 
201function ComposerInput() {
202 const {
203 state,
204 actions: { update },
205 meta: { inputRef },
206 } = use(ComposerContext)
207 return (
208 <TextInput
209 ref={inputRef}
210 value={state.input}
211 onChangeText={(text) => update((s) => ({ ...s, input: text }))}
212 />
213 )
214}
215 
216function ComposerSubmit() {
217 const {
218 actions: { submit },
219 } = use(ComposerContext)
220 return <Button onPress={submit}>Send</Button>
221}
222 
223// Export as compound component
224const Composer = {
225 Provider: ComposerProvider,
226 Frame: ComposerFrame,
227 Input: ComposerInput,
228 Submit: ComposerSubmit,
229 Header: ComposerHeader,
230 Footer: ComposerFooter,
231 Attachments: ComposerAttachments,
232 Formatting: ComposerFormatting,
233 Emojis: ComposerEmojis,
234}
235```
236 
237**Usage:**
238 
239```tsx
240<Composer.Provider state={state} actions={actions} meta={meta}>
241 <Composer.Frame>
242 <Composer.Header />
243 <Composer.Input />
244 <Composer.Footer>
245 <Composer.Formatting />
246 <Composer.Submit />
247 </Composer.Footer>
248 </Composer.Frame>
249</Composer.Provider>
250```
251 
252Consumers explicitly compose exactly what they need. No hidden conditionals. And the state, actions and meta are dependency-injected by a parent provider, allowing multiple usages of the same component structure.
253 
254---
255 
256## 2. State Management
257 
258**Impact: MEDIUM**
259 
260Patterns for lifting state and managing shared context across
261composed components.
262 
263### 2.1 Decouple State Management from UI
264 
265**Impact: MEDIUM (enables swapping state implementations without changing UI)**
266 
267The provider component should be the only place that knows how state is managed.
268 
269UI components consume the context interface—they don't know if state comes from
270 
271useState, Zustand, or a server sync.
272 
273**Incorrect: UI coupled to state implementation**
274 
275```tsx
276function ChannelComposer({ channelId }: { channelId: string }) {
277 // UI component knows about global state implementation
278 const state = useGlobalChannelState(channelId)
279 const { submit, updateInput } = useChannelSync(channelId)
280 
281 return (
282 <Composer.Frame>
283 <Composer.Input
284 value={state.input}
285 onChange={(text) => sync.updateInput(text)}
286 />
287 <Composer.Submit onPress={() => sync.submit()} />
288 </Composer.Frame>
289 )
290}
291```
292 
293**Correct: state management isolated in provider**
294 
295```tsx
296// Provider handles all state management details
297function ChannelProvider({
298 channelId,
299 children,
300}: {
301 channelId: string
302 children: React.ReactNode
303}) {
304 const { state, update, submit } = useGlobalChannel(channelId)
305 const inputRef = useRef(null)
306 
307 return (
308 <Composer.Provider
309 state={state}
310 actions={{ update, submit }}
311 meta={{ inputRef }}
312 >
313 {children}
314 </Composer.Provider>
315 )
316}
317 
318// UI component only knows about the context interface
319function ChannelComposer() {
320 return (
321 <Composer.Frame>
322 <Composer.Header />
323 <Composer.Input />
324 <Composer.Footer>
325 <Composer.Submit />
326 </Composer.Footer>
327 </Composer.Frame>
328 )
329}
330 
331// Usage
332function Channel({ channelId }: { channelId: string }) {
333 return (
334 <ChannelProvider channelId={channelId}>
335 <ChannelComposer />
336 </ChannelProvider>
337 )
338}
339```
340 
341**Different providers, same UI:**
342 
343```tsx
344// Local state for ephemeral forms
345function ForwardMessageProvider({ children }) {
346 const [state, setState] = useState(initialState)
347 const forwardMessage = useForwardMessage()
348 
349 return (
350 <Composer.Provider
351 state={state}
352 actions={{ update: setState, submit: forwardMessage }}
353 >
354 {children}
355 </Composer.Provider>
356 )
357}
358 
359// Global synced state for channels
360function ChannelProvider({ channelId, children }) {
361 const { state, update, submit } = useGlobalChannel(channelId)
362 
363 return (
364 <Composer.Provider state={state} actions={{ update, submit }}>
365 {children}
366 </Composer.Provider>
367 )
368}
369```
370 
371The same `Composer.Input` component works with both providers because it only
372 
373depends on the context interface, not the implementation.
374 
375### 2.2 Define Generic Context Interfaces for Dependency Injection
376 
377**Impact: HIGH (enables dependency-injectable state across use-cases)**
378 
379Define a **generic interface** for your component context with three parts:
380 
381`state`, `actions`, and `meta`. This interface is a contract that any provider
382 
383can implement—enabling the same UI components to work with completely different
384 
385state implementations.
386 
387**Core principle:** Lift state, compose internals, make state
388 
389dependency-injectable.
390 
391**Incorrect: UI coupled to specific state implementation**
392 
393```tsx
394function ComposerInput() {
395 // Tightly coupled to a specific hook
396 const { input, setInput } = useChannelComposerState()
397 return <TextInput value={input} onChangeText={setInput} />
398}
399```
400 
401**Correct: generic interface enables dependency injection**
402 
403```tsx
404// Define a GENERIC interface that any provider can implement
405interface ComposerState {
406 input: string
407 attachments: Attachment[]
408 isSubmitting: boolean
409}
410 
411interface ComposerActions {
412 update: (updater: (state: ComposerState) => ComposerState) => void
413 submit: () => void
414}
415 
416interface ComposerMeta {
417 inputRef: React.RefObject<TextInput>
418}
419 
420interface ComposerContextValue {
421 state: ComposerState
422 actions: ComposerActions
423 meta: ComposerMeta
424}
425 
426const ComposerContext = createContext<ComposerContextValue | null>(null)
427```
428 
429**UI components consume the interface, not the implementation:**
430 
431```tsx
432function ComposerInput() {
433 const {
434 state,
435 actions: { update },
436 meta,
437 } = use(ComposerContext)
438 
439 // This component works with ANY provider that implements the interface
440 return (
441 <TextInput
442 ref={meta.inputRef}
443 value={state.input}
444 onChangeText={(text) => update((s) => ({ ...s, input: text }))}
445 />
446 )
447}
448```
449 
450**Different providers implement the same interface:**
451 
452```tsx
453// Provider A: Local state for ephemeral forms
454function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
455 const [state, setState] = useState(initialState)
456 const inputRef = useRef(null)
457 const submit = useForwardMessage()
458 
459 return (
460 <ComposerContext
461 value={{
462 state,
463 actions: { update: setState, submit },
464 meta: { inputRef },
465 }}
466 >
467 {children}
468 </ComposerContext>
469 )
470}
471 
472// Provider B: Global synced state for channels
473function ChannelProvider({ channelId, children }: Props) {
474 const { state, update, submit } = useGlobalChannel(channelId)
475 const inputRef = useRef(null)
476 
477 return (
478 <ComposerContext
479 value={{
480 state,
481 actions: { update, submit },
482 meta: { inputRef },
483 }}
484 >
485 {children}
486 </ComposerContext>
487 )
488}
489```
490 
491**The same composed UI works with both:**
492 
493```tsx
494// Works with ForwardMessageProvider (local state)
495<ForwardMessageProvider>
496 <Composer.Frame>
497 <Composer.Input />
498 <Composer.Submit />
499 </Composer.Frame>
500</ForwardMessageProvider>
501 
502// Works with ChannelProvider (global synced state)
503<ChannelProvider channelId="abc">
504 <Composer.Frame>
505 <Composer.Input />
506 <Composer.Submit />
507 </Composer.Frame>
508</ChannelProvider>
509```
510 
511**Custom UI outside the component can access state and actions:**
512 
513```tsx
514function ForwardMessageDialog() {
515 return (
516 <ForwardMessageProvider>
517 <Dialog>
518 {/* The composer UI */}
519 <Composer.Frame>
520 <Composer.Input placeholder="Add a message, if you'd like." />
521 <Composer.Footer>
522 <Composer.Formatting />
523 <Composer.Emojis />
524 </Composer.Footer>
525 </Composer.Frame>
526 
527 {/* Custom UI OUTSIDE the composer, but INSIDE the provider */}
528 <MessagePreview />
529 
530 {/* Actions at the bottom of the dialog */}
531 <DialogActions>
532 <CancelButton />
533 <ForwardButton />
534 </DialogActions>
535 </Dialog>
536 </ForwardMessageProvider>
537 )
538}
539 
540// This button lives OUTSIDE Composer.Frame but can still submit based on its context!
541function ForwardButton() {
542 const {
543 actions: { submit },
544 } = use(ComposerContext)
545 return <Button onPress={submit}>Forward</Button>
546}
547 
548// This preview lives OUTSIDE Composer.Frame but can read composer's state!
549function MessagePreview() {
550 const { state } = use(ComposerContext)
551 return <Preview message={state.input} attachments={state.attachments} />
552}
553```
554 
555The provider boundary is what matters—not the visual nesting. Components that
556 
557need shared state don't have to be inside the `Composer.Frame`. They just need
558 
559to be within the provider.
560 
561The `ForwardButton` and `MessagePreview` are not visually inside the composer
562 
563box, but they can still access its state and actions. This is the power of
564 
565lifting state into providers.
566 
567The UI is reusable bits you compose together. The state is dependency-injected
568 
569by the provider. Swap the provider, keep the UI.
570 
571### 2.3 Lift State into Provider Components
572 
573**Impact: HIGH (enables state sharing outside component boundaries)**
574 
575Move state management into dedicated provider components. This allows sibling
576 
577components outside the main UI to access and modify state without prop drilling
578 
579or awkward refs.
580 
581**Incorrect: state trapped inside component**
582 
583```tsx
584function ForwardMessageComposer() {
585 const [state, setState] = useState(initialState)
586 const forwardMessage = useForwardMessage()
587 
588 return (
589 <Composer.Frame>
590 <Composer.Input />
591 <Composer.Footer />
592 </Composer.Frame>
593 )
594}
595 
596// Problem: How does this button access composer state?
597function ForwardMessageDialog() {
598 return (
599 <Dialog>
600 <ForwardMessageComposer />
601 <MessagePreview /> {/* Needs composer state */}
602 <DialogActions>
603 <CancelButton />
604 <ForwardButton /> {/* Needs to call submit */}
605 </DialogActions>
606 </Dialog>
607 )
608}
609```
610 
611**Incorrect: useEffect to sync state up**
612 
613```tsx
614function ForwardMessageDialog() {
615 const [input, setInput] = useState('')
616 return (
617 <Dialog>
618 <ForwardMessageComposer onInputChange={setInput} />
619 <MessagePreview input={input} />
620 </Dialog>
621 )
622}
623 
624function ForwardMessageComposer({ onInputChange }) {
625 const [state, setState] = useState(initialState)
626 useEffect(() => {
627 onInputChange(state.input) // Sync on every change 😬
628 }, [state.input])
629}
630```
631 
632**Incorrect: reading state from ref on submit**
633 
634```tsx
635function ForwardMessageDialog() {
636 const stateRef = useRef(null)
637 return (
638 <Dialog>
639 <ForwardMessageComposer stateRef={stateRef} />
640 <ForwardButton onPress={() => submit(stateRef.current)} />
641 </Dialog>
642 )
643}
644```
645 
646**Correct: state lifted to provider**
647 
648```tsx
649function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
650 const [state, setState] = useState(initialState)
651 const forwardMessage = useForwardMessage()
652 const inputRef = useRef(null)
653 
654 return (
655 <Composer.Provider
656 state={state}
657 actions={{ update: setState, submit: forwardMessage }}
658 meta={{ inputRef }}
659 >
660 {children}
661 </Composer.Provider>
662 )
663}
664 
665function ForwardMessageDialog() {
666 return (
667 <ForwardMessageProvider>
668 <Dialog>
669 <ForwardMessageComposer />
670 <MessagePreview /> {/* Custom components can access state and actions */}
671 <DialogActions>
672 <CancelButton />
673 <ForwardButton /> {/* Custom components can access state and actions */}
674 </DialogActions>
675 </Dialog>
676 </ForwardMessageProvider>
677 )
678}
679 
680function ForwardButton() {
681 const { actions } = use(Composer.Context)
682 return <Button onPress={actions.submit}>Forward</Button>
683}
684```
685 
686The ForwardButton lives outside the Composer.Frame but still has access to the
687 
688submit action because it's within the provider. Even though it's a one-off
689 
690component, it can still access the composer's state and actions from outside the
691 
692UI itself.
693 
694**Key insight:** Components that need shared state don't have to be visually
695 
696nested inside each other—they just need to be within the same provider.
697 
698---
699 
700## 3. Implementation Patterns
701 
702**Impact: MEDIUM**
703 
704Specific techniques for implementing compound components and
705context providers.
706 
707### 3.1 Create Explicit Component Variants
708 
709**Impact: MEDIUM (self-documenting code, no hidden conditionals)**
710 
711Instead of one component with many boolean props, create explicit variant
712 
713components. Each variant composes the pieces it needs. The code documents
714 
715itself.
716 
717**Incorrect: one component, many modes**
718 
719```tsx
720// What does this component actually render?
721<Composer
722 isThread
723 isEditing={false}
724 channelId='abc'
725 showAttachments
726 showFormatting={false}
727/>
728```
729 
730**Correct: explicit variants**
731 
732```tsx
733// Immediately clear what this renders
734<ThreadComposer channelId="abc" />
735 
736// Or
737<EditMessageComposer messageId="xyz" />
738 
739// Or
740<ForwardMessageComposer messageId="123" />
741```
742 
743Each implementation is unique, explicit and self-contained. Yet they can each
744 
745use shared parts.
746 
747**Implementation:**
748 
749```tsx
750function ThreadComposer({ channelId }: { channelId: string }) {
751 return (
752 <ThreadProvider channelId={channelId}>
753 <Composer.Frame>
754 <Composer.Input />
755 <AlsoSendToChannelField channelId={channelId} />
756 <Composer.Footer>
757 <Composer.Formatting />
758 <Composer.Emojis />
759 <Composer.Submit />
760 </Composer.Footer>
761 </Composer.Frame>
762 </ThreadProvider>
763 )
764}
765 
766function EditMessageComposer({ messageId }: { messageId: string }) {
767 return (
768 <EditMessageProvider messageId={messageId}>
769 <Composer.Frame>
770 <Composer.Input />
771 <Composer.Footer>
772 <Composer.Formatting />
773 <Composer.Emojis />
774 <Composer.CancelEdit />
775 <Composer.SaveEdit />
776 </Composer.Footer>
777 </Composer.Frame>
778 </EditMessageProvider>
779 )
780}
781 
782function ForwardMessageComposer({ messageId }: { messageId: string }) {
783 return (
784 <ForwardMessageProvider messageId={messageId}>
785 <Composer.Frame>
786 <Composer.Input placeholder="Add a message, if you'd like." />
787 <Composer.Footer>
788 <Composer.Formatting />
789 <Composer.Emojis />
790 <Composer.Mentions />
791 </Composer.Footer>
792 </Composer.Frame>
793 </ForwardMessageProvider>
794 )
795}
796```
797 
798Each variant is explicit about:
799 
800- What provider/state it uses
801 
802- What UI elements it includes
803 
804- What actions are available
805 
806No boolean prop combinations to reason about. No impossible states.
807 
808### 3.2 Prefer Composing Children Over Render Props
809 
810**Impact: MEDIUM (cleaner composition, better readability)**
811 
812Use `children` for composition instead of `renderX` props. Children are more
813 
814readable, compose naturally, and don't require understanding callback
815 
816signatures.
817 
818**Incorrect: render props**
819 
820```tsx
821function Composer({
822 renderHeader,
823 renderFooter,
824 renderActions,
825}: {
826 renderHeader?: () => React.ReactNode
827 renderFooter?: () => React.ReactNode
828 renderActions?: () => React.ReactNode
829}) {
830 return (
831 <form>
832 {renderHeader?.()}
833 <Input />
834 {renderFooter ? renderFooter() : <DefaultFooter />}
835 {renderActions?.()}
836 </form>
837 )
838}
839 
840// Usage is awkward and inflexible
841return (
842 <Composer
843 renderHeader={() => <CustomHeader />}
844 renderFooter={() => (
845 <>
846 <Formatting />
847 <Emojis />
848 </>
849 )}
850 renderActions={() => <SubmitButton />}
851 />
852)
853```
854 
855**Correct: compound components with children**
856 
857```tsx
858function ComposerFrame({ children }: { children: React.ReactNode }) {
859 return <form>{children}</form>
860}
861 
862function ComposerFooter({ children }: { children: React.ReactNode }) {
863 return <footer className='flex'>{children}</footer>
864}
865 
866// Usage is flexible
867return (
868 <Composer.Frame>
869 <CustomHeader />
870 <Composer.Input />
871 <Composer.Footer>
872 <Composer.Formatting />
873 <Composer.Emojis />
874 <SubmitButton />
875 </Composer.Footer>
876 </Composer.Frame>
877)
878```
879 
880**When render props are appropriate:**
881 
882```tsx
883// Render props work well when you need to pass data back
884<List
885 data={items}
886 renderItem={({ item, index }) => <Item item={item} index={index} />}
887/>
888```
889 
890Use render props when the parent needs to provide data or state to the child.
891 
892Use children when composing static structure.
893 
894---
895 
896## 4. React 19 APIs
897 
898**Impact: MEDIUM**
899 
900React 19+ only. Don't use `forwardRef`; use `use()` instead of `useContext()`.
901 
902### 4.1 React 19 API Changes
903 
904**Impact: MEDIUM (cleaner component definitions and context usage)**
905 
906> **⚠️ React 19+ only.** Skip this if you're on React 18 or earlier.
907 
908In React 19, `ref` is now a regular prop (no `forwardRef` wrapper needed), and `use()` replaces `useContext()`.
909 
910**Incorrect: forwardRef in React 19**
911 
912```tsx
913const ComposerInput = forwardRef<TextInput, Props>((props, ref) => {
914 return <TextInput ref={ref} {...props} />
915})
916```
917 
918**Correct: ref as a regular prop**
919 
920```tsx
921function ComposerInput({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) {
922 return <TextInput ref={ref} {...props} />
923}
924```
925 
926**Incorrect: useContext in React 19**
927 
928```tsx
929const value = useContext(MyContext)
930```
931 
932**Correct: use instead of useContext**
933 
934```tsx
935const value = use(MyContext)
936```
937 
938`use()` can also be called conditionally, unlike `useContext()`.
939 
940---
941 
942## References
943 
9441. [https://react.dev](https://react.dev)
9452. [https://react.dev/learn/passing-data-deeply-with-context](https://react.dev/learn/passing-data-deeply-with-context)
9463. [https://react.dev/reference/react/use](https://react.dev/reference/react/use)
947 

Sections

  • React Composition Patterns
  • Abstract
  • Table of Contents
  • 1. Component Architecture
  • 1.1 Avoid Boolean Prop Proliferation
  • 1.2 Use Compound Components
  • 2. State Management
  • 2.1 Decouple State Management from UI
  • 2.2 Define Generic Context Interfaces for Dependency Injection
  • 2.3 Lift State into Provider Components
  • 3. Implementation Patterns
  • 3.1 Create Explicit Component Variants
  • 3.2 Prefer Composing Children Over Render Props
  • 4. React 19 APIs
  • 4.1 React 19 API Changes
  • References

What it covers

code-styleapiuido-not

Stack — with the evidence

typescript

(1.00)

turborepo

(1.00)

eslint

(1.00)

node

(0.70)

react

(0.70)

nextjs

(0.70)

fastapi

(0.70)

react-native

(0.70)

expo

(0.70)

postgres

(0.70)

redis

(0.70)

tailwind

(0.70)

vitest

(0.70)

pytest

(0.70)

ruff

(0.70)

javascript

(0.60)

monorepo

(0.60)

pnpm

(0.60)

github-actions

(0.60)

python

(0.50)

Format

AGENTS.md

A plain-markdown README for coding agents, deliberately unopinionated: no frontmatter, no globs, no vendor keys. That minimalism is why it became the one file a dozen different agents will read, and why it carries the least per-file targeting power of any format here.

What the corpus says about it

Repository

Owner
itxSaaad
Language
—
License
—
Archived
no

All configs in this repo

Also in itxSaaad/medlens-plus-app

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
itxSaaad/medlens-plus-app.cursor/rules/testing.mdc · 0Cursor rulestypescriptturborepo+18testtesting-strategyapimonorepo29/1003 days ago
itxSaaad/medlens-plus-app.claude/skills/web-frontend/references/composition-patterns/AGENTS.md · 0AGENTS.mdtypescriptturborepo+18styleapiuido-not57/1003 days ago
itxSaaad/medlens-plus-app.claude/skills/web-frontend/references/react-best-practices/AGENTS.md · 0AGENTS.mdtypescriptturborepo+18buildstyletypessecurity+665/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/agent-discipline.mdc · 0Cursor rulestypescriptturborepo+18teststyleagent-behaviour53/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/devops-ci.mdc · 0Cursor rulestypescriptturborepo+18securitydo-not23/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/engineering-standards.mdc · 0Cursor rulestypescriptturborepo+18test35/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/fastapi-backend.mdc · 0Cursor rulestypescriptturborepo+18testlint-formatstyle66/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/frontend-quality.mdc · 0Cursor rulestypescriptturborepo+18securityui33/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/github-delivery.mdc · 0Cursor rulestypescriptturborepo+18git16/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/graphify.mdc · 0Cursor rulestypescriptturborepo+18do-not45/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/langgraph-ai-workflows.mdc · 0Cursor rulestypescriptturborepo+18do-not32/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/medical-safety.mdc · 0Cursor rulestypescriptturborepo+18do-not23/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/nextjs-frontend.mdc · 0Cursor rulestypescriptturborepo+18teststylearch80/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/pr-quality-gate.mdc · 0Cursor rulestypescriptturborepo+18testgit43/1003 days ago
itxSaaad/medlens-plus-app.cursor/rules/technical-seo.mdc · 0Cursor rulestypescriptturborepo+18no sections24/1003 days ago
itxSaaad/medlens-plus-app.cursor/skills/web-frontend/references/react-best-practices/AGENTS.md · 0AGENTS.mdtypescriptturborepo+18buildstyletypessecurity+665/1003 days ago
itxSaaad/medlens-plus-app.github/copilot-instructions.md · 0Copilot instructionstypescriptturborepo+18testgitdo-notagent-behaviour+170/1003 days ago
itxSaaad/medlens-plus-appAGENTS.md · 0AGENTS.mdtypescriptturborepo+18gitdo-notagent-behaviour59/1003 days ago
itxSaaad/medlens-plus-appapps/mobile/CLAUDE.md · 0CLAUDE.mdtypescriptreact-native+18stylearchmonorepoagent-behaviour86/1003 days ago
itxSaaad/medlens-plus-appCLAUDE.md · 0CLAUDE.mdtypescriptturborepo+18testgitmonorepodo-not+176/1003 days ago
Diff against .cursor/rules/testing.mdc Diff against .claude/skills/web-frontend/references/composition-patterns/AGENTS.md Diff against .claude/skills/web-frontend/references/react-best-practices/AGENTS.md Diff against .cursor/rules/agent-discipline.mdc Diff against .cursor/rules/devops-ci.mdc Diff against .cursor/rules/engineering-standards.mdc Diff against .cursor/rules/fastapi-backend.mdc Diff against .cursor/rules/frontend-quality.mdc Diff against .cursor/rules/github-delivery.mdc Diff against .cursor/rules/graphify.mdc Diff against .cursor/rules/langgraph-ai-workflows.mdc Diff against .cursor/rules/medical-safety.mdc Diff against .cursor/rules/nextjs-frontend.mdc Diff against .cursor/rules/pr-quality-gate.mdc Diff against .cursor/rules/technical-seo.mdc Diff against .cursor/skills/web-frontend/references/react-best-practices/AGENTS.md Diff against .github/copilot-instructions.md Diff against AGENTS.md Diff against apps/mobile/CLAUDE.md Diff against CLAUDE.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
mui/material-uiAGENTS.md · 99kAGENTS.mdtypescriptjavascript+13setupbuildtestlint-format+9100/1003 days ago
TryGhost/Ghoste2e/AGENTS.md · 55kAGENTS.mdtypescriptjavascript+12setupteststylearch+2100/1003 days ago
SkeneTechnologies/skene-cookbookAGENTS.md · 51AGENTS.mdpythoneslint+4setupbuildtestlint-format+7100/1002 days ago
duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70AGENTS.mdtypescriptjavascript+5buildteststylearch+3100/1003 days ago
n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199kAGENTS.mdtypescriptlangchain+16buildteststylearch+3100/1003 days ago
aaif-goose/gooseAGENTS.md · 52kAGENTS.mdrusttypescript+2setupbuildtestlint-format+6100/1003 days ago
trick77/agents-md-syncAGENTS.md · 2AGENTS.mdtypescriptnode+4setupbuildteststyle+5100/1003 days ago
code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 67kAGENTS.mdtypescriptbun+10setupbuildtestlint-format+6100/1002 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack