--- name: relay-mutations-patterns user-invocable: false description: Use when relay mutations with optimistic updates, connections, declarative mutations, and error handling. allowed-tools: - Read - Write - Edit - Grep - Glob - Bash --- # Relay Mutations Patterns Master Relay mutations for building interactive applications with optimistic updates, connection handling, and declarative data updates. ## Overview Relay mutations provide a declarative way to update data with automatic cache updates, optimistic responses, and rollback on error. Mutations integrate seamlessly with Relay's normalized cache and connection protocol. ## Installation and Setup ### Mutation Configuration ```javascript // mutations/CreatePostMutation.js import { graphql, commitMutation } from 'react-relay'; import environment from '../RelayEnvironment'; const mutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { postEdge { __typename cursor node { id title body createdAt author { id name } } } } } `; export default function createPost(title, body) { return new Promise((resolve, reject) => { commitMutation(environment, { mutation, variables: { input: { title, body } }, onCompleted: (response, errors) => { if (errors) { reject(errors); } else { resolve(response); } }, onError: reject }); }); } ``` ## Core Patterns ### 1. Basic Mutation ```javascript // CreatePost.jsx import { graphql, useMutation } from 'react-relay'; const CreatePostMutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { post { id title body author { id name } } } } `; function CreatePost() { const [commit, isInFlight] = useMutation(CreatePostMutation); const handleSubmit = (title, body) => { commit({ variables: { input: { title, body } }, onCompleted: (response, errors) => { if (errors) { console.error('Errors:', errors); } else { console.log('Post created:', response.createPost.post); } }, onError: (error) => { console.error('Network error:', error); } }); }; return (
{ e.preventDefault(); handleSubmit(e.target.title.value, e.target.body.value); }}>