hoc-pattern
Teaches the Higher-Order Component (HOC) pattern for logic reuse. Use when you need to share cross-cutting concerns like authentication, logging, or data fetching across multiple components.
What this skill does
# HOC Pattern
## Table of Contents
- [When to Use](#when-to-use)
- [When NOT to Use](#when-not-to-use)
- [Instructions](#instructions)
- [Details](#details)
- [Source](#source)
Within our application, we often want to use the same logic in multiple components. This logic can include applying a certain styling to components, requiring authorization, or adding a global state.
One way of being able to reuse the same logic in multiple components, is by using the **higher order component** pattern. This pattern allows us to reuse component logic throughout our application.
## When to Use
- Use this when the same uncustomized behavior needs to be applied to many components
- This is helpful when a component should work standalone without the added custom logic
## When NOT to Use
- When custom hooks can achieve the same result with less nesting and better readability
- In new React 18+ code where hooks are the idiomatic approach to sharing stateful logic
- When the HOC wrapper adds prop-name collisions or obscures the component tree in DevTools
## Instructions
- Create a function that takes a component and returns a new component with enhanced behavior
- Avoid naming collisions by renaming or merging props in the HOC
- Prefer React Hooks over HOCs for most new code to avoid wrapper hell and deep nesting
- Compose multiple HOCs carefully and be aware that the order of composition matters
## Details
A Higher Order Component (HOC) is a component that receives another component. The HOC contains certain logic that we want to apply to the component that we pass as a parameter. After applying that logic, the HOC returns the element with the additional logic.
Say that we always wanted to add a certain styling to multiple components in our application. Instead of creating a `style` object locally each time, we can simply create a HOC that adds the `style` objects to the component that we pass to it:
```js
function withStyles(Component) {
return props => {
const style = { padding: '0.2rem', margin: '1rem' }
return <Component style={style} {...props} />
}
}
const Button = () => <button>Click me!</button>
const Text = () => <p>Hello World!</p>
const StyledButton = withStyles(Button)
const StyledText = withStyles(Text)
```
We just created a StyledButton and StyledText component, which are the modified versions of the Button and Text component. They now both contain the style that got added in the `withStyles` HOC!
Let's improve the user experience a little bit. When we're fetching the data, we want to show a `"Loading..."` screen to the user. Instead of adding data to the `DogImages` component directly, we can use a Higher Order Component that adds this logic for us.
Let's create a HOC called `withLoader`. A HOC should receive a component, and return that component. In this case, the `withLoader` HOC should receive the element which should display `Loading…` until the data is fetched.
```js
function withLoader(Element) {
return (props) => <Element />;
}
```
However, we don't just want to return the element it received. Instead, we want this element to contain logic that tells us whether the data is still loading or not.
To make the `withLoader` HOC very reusable, we won't hardcode the Dog API url in that component. Instead, we can pass the URL as an argument to the `withLoader` HOC, so this loader can be used on any component that needs a loading indicator while fetching data from a different API endpoint.
```js
function withLoader(Element, url) {
return (props) => {};
}
```
A HOC returns an element, a functional component `props => {}` in this case, to which we want to add the logic that allows us to display a text with `Loading…` as the data is still being fetched. Once the data has been fetched, the component should pass the fetched data as a prop.
We just created a HOC that can receive any component and url.
1. In the `useEffect` hook, the `withLoader` HOC fetches the data from the API endpoint that we pass as the value of `url`. While the data hasn't returned yet, we return the element containing the `Loading...` text.
2. Once the data has been fetched, we set `data` equal to the data that has been fetched. Since `data` is no longer `null`, we can display the element that we passed to the HOC!
So, how can we add this behavior to our application? In `DogImages.js`, we no longer want to just export the plain `DogImages` component. Instead, we want to export the "wrapped" `withLoading` HOC around the `DogImages` component.
```js
export default withLoader(
DogImages,
"https://dog.ceo/api/breed/labrador/images/random/6"
);
```
The Higher Order Component pattern allows us to provide the same logic to multiple components, while keeping all the logic in one single place. The `withLoader` HOC doesn't care about the component or url it receives: as long as it's a valid component and a valid API endpoint, it'll simply pass the data from that API endpoint to the component that we pass.
### Composing
We can also compose multiple Higher Order Components. Let's say that we also want to add functionality that shows a `Hovering!` text box when the user hovers over the `DogImages` list.
We need to create a HOC that provides a `hovering` prop to the element that we pass. Based on that prop, we can conditionally render the text box based on whether the user is hovering over the `DogImages` list.
We can now wrap the `withHover` HOC around the `withLoader` HOC.
The `DogImages` element now contains all props that we passed from both `withHover` and `withLoader`. We can now conditionally render the `Hovering!` text box, based on whether the value of the `hovering` prop is `true` or `false`.
> A well-known library used for composing HOCs is [recompose](https://github.com/acdlite/recompose). Since HOCs can largely be replaced by React Hooks, the recompose library is no longer maintained.
### Hooks
In some cases, we can replace the HOC pattern with React Hooks.
Let's replace the `withHover` HOC with a `useHover` hook. Instead of having a higher order component, we export a hook that adds a `mouseOver` and `mouseLeave` event listener to the element. We cannot pass the element anymore like we did with the HOC. Instead, we'll return a `ref` from the hook that should get the `mouseOver` and `mouseLeave` events.
The `useEffect` hook adds an event listener to the component, and sets the value `hovering` to `true` or `false`, depending on whether the user is currently hovering over the element. Both the `ref` and `hovering` values need to be returned from the hook: `ref` to add a ref to the component that should receive the `mouseOver` and `mouseLeave` events, and `hovering` in order to be able to conditionally render the `Hovering!` text box.
Instead of wrapping the `DogImages` component with the `withHover` component, we can simply use the `useHover` hook within the component directly.
Generally speaking, React Hooks don't replace the HOC pattern.
_"In most cases, Hooks will be sufficient and can help reduce nesting in your tree."_ - [React Docs](https://reactjs.org/docs/hooks-faq.html#do-hooks-replace-render-props-and-higher-order-components)
As the React docs tell us, using Hooks can reduce the depth of the component tree. Using the HOC pattern, it's easy to end up with a deeply nested component tree.
```js
<withAuth>
<withLayout>
<withLogging>
<Component />
</withLogging>
</withLayout>
</withAuth>
```
By adding a Hook to the component directly, we no longer have to wrap components.
Using Higher Order Components makes it possible to provide the same logic to many components, while keeping that logic all in one single place. Hooks allow us to add custom behavior from within the component, which could potentially increase the risk of introducing bugs compared to the HOC pattern if multiple components rely on this behavior.
**Best use-cases for a HOC**:
- The _same, uncustomized_ behavior needs to be used by Related in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.