probo / rules
getprobo/probo/.cursor/rules/relay-connection-item-components.mdc
Extract connection list items (table rows, list entries) into their own fragment component
Cursor rule1.4k starsChanged 3 months ago
What's in it
- Extract connection items into fragment components
- Pattern
- Naming
---
description: Extract connection list items (table rows, list entries) into their own fragment component
globs: "**/*.tsx"
alwaysApply: false
---
# Extract connection items into fragment components
When rendering items from a Relay connection (e.g. `edges.map(…)`), each item
MUST be rendered by a dedicated component that owns its own fragment — never
inline the rendering of node fields directly in the parent's `.map()` body.
This ensures:
- Data requirements are colocated with the rendering component
- Adding/removing fields in an item doesn't bloat the parent's fragment
- The item component is independently testable and reusable
## Pattern
```tsx
// _components/ThingListItem.tsx — owns its fragment
const thingListItemFragment = graphql`
fragment ThingListItem_thing on Thing {
id
name
status
}
`;
interface ThingListItemProps {
thingKey: ThingListItem_thing$key;
}
export function ThingListItem({ thingKey }: ThingListItemProps) {
const thing = useFragment(thingListItemFragment, thingKey);
return (
<Tr>
<Td>{thing.name}</Td>
<Td>{thing.status}</Td>
</Tr>
);
}
```
```tsx
// Parent — spreads the item fragment in its connection and renders the component
const parentFragment = graphql`
fragment ParentPage_things on Query
@refetchable(queryName: "ParentPageRefetchQuery") {
things(first: $first, after: $after) @connection(key: "ParentPage_things") {
edges {
node {
id
...ThingListItem_thing
}
}
}
}
`;
// In JSX:
{things.map(thing => (
<ThingListItem key={thing.id} thingKey={thing} />
))}
```
## Naming
- File: `_components/<NodeType>ListItem.tsx` — the canonical connection-item
suffix, regardless of whether the item renders as a table row, a card, or a
plain list entry (the layout is internal to the component, not its identity).
Do **not** use `*Row` or `*Card` suffixes.
- Fragment: `<ComponentName>_<typeName>` (e.g. `ThingListItem_thing`)
- Prop: `<typeName>Key` (e.g. `thingKey`)
See `contrib/claude/react-components.md` for the full suffix taxonomy.
More agent context in getprobo/probo
29 other files this repository gives its agents.
AGENTS.md
CLAUDE.md
Cursor rule
- .cursor/rules/code-comments.mdc
- .cursor/rules/config-propagation.mdc
- .cursor/rules/coredata-migrations.mdc
- .cursor/rules/detail-page-back-link.mdc
- .cursor/rules/git-commit-signing.mdc
- .cursor/rules/git-commit-style.mdc
- .cursor/rules/go-authorize-scope.mdc
- .cursor/rules/go-coredata-load-naming.mdc
- .cursor/rules/go-declarations.mdc
- .cursor/rules/go-delete-no-rows-check.mdc
- .cursor/rules/go-error-handling.mdc
- .cursor/rules/go-imports.mdc
- .cursor/rules/go-logging.mdc
- .cursor/rules/go-multiline-params.mdc
- .cursor/rules/go-naming-conventions.mdc
- .cursor/rules/go-pg-constraint-check.mdc
- .cursor/rules/go-upsert-returning-id.mdc
- .cursor/rules/go-url-construction.mdc
- .cursor/rules/list-filtering.mdc
- .cursor/rules/no-outlet-context-data.mdc
- .cursor/rules/prompt-style.mdc
- .cursor/rules/react-named-exports-lazy-entry.mdc
- .cursor/rules/relay-fragments-not-data-props.mdc
- .cursor/rules/relay-required-directive.mdc
- .cursor/rules/skeleton-width-sync.mdc
- .cursor/rules/template-files.mdc
- .cursor/rules/v2-color-scale.mdc
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
Reports can't be read right now.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

