Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
3.1 KiB
Markdown
126 lines
3.1 KiB
Markdown
---
|
|
title: Lift State into Provider Components
|
|
impact: HIGH
|
|
impactDescription: enables state sharing outside component boundaries
|
|
tags: composition, state, context, providers
|
|
---
|
|
|
|
## Lift State into Provider Components
|
|
|
|
Move state management into dedicated provider components. This allows sibling
|
|
components outside the main UI to access and modify state without prop drilling
|
|
or awkward refs.
|
|
|
|
**Incorrect (state trapped inside component):**
|
|
|
|
```tsx
|
|
function ForwardMessageComposer() {
|
|
const [state, setState] = useState(initialState)
|
|
const forwardMessage = useForwardMessage()
|
|
|
|
return (
|
|
<Composer.Frame>
|
|
<Composer.Input />
|
|
<Composer.Footer />
|
|
</Composer.Frame>
|
|
)
|
|
}
|
|
|
|
// Problem: How does this button access composer state?
|
|
function ForwardMessageDialog() {
|
|
return (
|
|
<Dialog>
|
|
<ForwardMessageComposer />
|
|
<MessagePreview /> {/* Needs composer state */}
|
|
<DialogActions>
|
|
<CancelButton />
|
|
<ForwardButton /> {/* Needs to call submit */}
|
|
</DialogActions>
|
|
</Dialog>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Incorrect (useEffect to sync state up):**
|
|
|
|
```tsx
|
|
function ForwardMessageDialog() {
|
|
const [input, setInput] = useState('')
|
|
return (
|
|
<Dialog>
|
|
<ForwardMessageComposer onInputChange={setInput} />
|
|
<MessagePreview input={input} />
|
|
</Dialog>
|
|
)
|
|
}
|
|
|
|
function ForwardMessageComposer({ onInputChange }) {
|
|
const [state, setState] = useState(initialState)
|
|
useEffect(() => {
|
|
onInputChange(state.input) // Sync on every change 😬
|
|
}, [state.input])
|
|
}
|
|
```
|
|
|
|
**Incorrect (reading state from ref on submit):**
|
|
|
|
```tsx
|
|
function ForwardMessageDialog() {
|
|
const stateRef = useRef(null)
|
|
return (
|
|
<Dialog>
|
|
<ForwardMessageComposer stateRef={stateRef} />
|
|
<ForwardButton onPress={() => submit(stateRef.current)} />
|
|
</Dialog>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Correct (state lifted to provider):**
|
|
|
|
```tsx
|
|
function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
|
|
const [state, setState] = useState(initialState)
|
|
const forwardMessage = useForwardMessage()
|
|
const inputRef = useRef(null)
|
|
|
|
return (
|
|
<Composer.Provider
|
|
state={state}
|
|
actions={{ update: setState, submit: forwardMessage }}
|
|
meta={{ inputRef }}
|
|
>
|
|
{children}
|
|
</Composer.Provider>
|
|
)
|
|
}
|
|
|
|
function ForwardMessageDialog() {
|
|
return (
|
|
<ForwardMessageProvider>
|
|
<Dialog>
|
|
<ForwardMessageComposer />
|
|
<MessagePreview /> {/* Custom components can access state and actions */}
|
|
<DialogActions>
|
|
<CancelButton />
|
|
<ForwardButton /> {/* Custom components can access state and actions */}
|
|
</DialogActions>
|
|
</Dialog>
|
|
</ForwardMessageProvider>
|
|
)
|
|
}
|
|
|
|
function ForwardButton() {
|
|
const { actions } = use(Composer.Context)
|
|
return <Button onPress={actions.submit}>Forward</Button>
|
|
}
|
|
```
|
|
|
|
The ForwardButton lives outside the Composer.Frame but still has access to the
|
|
submit action because it's within the provider. Even though it's a one-off
|
|
component, it can still access the composer's state and actions from outside the
|
|
UI itself.
|
|
|
|
**Key insight:** Components that need shared state don't have to be visually
|
|
nested inside each other—they just need to be within the same provider.
|