Generated banner for React18 Legacy Context
Generated logo for React18 Legacy Context

React18 Legacy Context

GitHubOfficialFirst committed by SaravananRajaramanDistributed by GitHub

  • Skill
  • Workflow
  • Software development
  • MIT
  • No issues found

From the author

Provides the complete migration pattern for React legacy context API (contextTypes, childContextTypes, getChildContext) to the modern createContext API. Use this skill whenever migrating legacy context in class components - this is always a cross-file migration requiring the provider AND all consumers to be updated together. Use it before touching any contextTypes or childContextTypes code, because migrating only the provider without the consumers (or vice versa) will cause a runtime failure. Always read this skill before writing any context migration - the cross-file coordination steps here prevent the most common context migration bugs.
— the description by SaravananRajaraman

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a systematic approach to migrating legacy React context (contextTypes, childContextTypes, getChildContext) to the modern createContext API. Because legacy context is removed in React 19, this migration is critical for upgrading codebases. The skill emphasizes that this is a cross-file operation requiring simultaneous updates to both the provider and all consumers to prevent runtime failures. It includes scanning commands, file templates, and strategies for handling multiple contexts.

What it does

  • Provides a step-by-step migration procedure for legacy React context.
  • Offers shell commands to identify legacy providers and consumers in a codebase.
  • Includes templates for creating new, modular context files.
  • Explains how to split combined legacy providers into individual modern context providers.
  • Details strategies for updating class-based consumers to modern standards.
  • Outlines the correct order of operations to avoid broken application states.

When to use it

  • When upgrading a React application to version 18 or preparing for version 19.
  • When refactoring class components that rely on legacy contextTypes.
  • When you need to replace deprecated getChildContext patterns.
  • When managing complex applications with multiple nested legacy contexts.

Advantages

  • Prevents common runtime errors caused by partial migrations.
  • Standardizes the structure of new context files across the project.
  • Provides clear, actionable steps to minimize downtime during refactoring.
  • Offers specific patterns for handling multiple contexts in a single component.

Usage examples

“How do I find all components using legacy context in my project?”
The agent provides grep commands to scan for childContextTypes, getChildContext, and contextTypes to map out the migration scope.
“I have a class component using multiple legacy contexts. How do I migrate it?”
The agent guides you to either use Context.Consumer render props or convert the component to a function component using multiple useContext hooks.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/github/react18-legacy-context/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip react18-legacy-context.zip -d .agents/skills

Documentation by SaravananRajaraman

React 18 Legacy Context Migration

Legacy context (contextTypes, childContextTypes, getChildContext) was deprecated in React 16.3 and warns in React 18.3.1. It is removed in React 19.

This Is Always a Cross-File Migration

Unlike most other migrations that touch one file at a time, context migration requires coordinating:

  1. Create the context object (usually a new file)

  2. Update the provider component

  3. Update every consumer component

Missing any consumer leaves the app broken - it will read from the wrong context or get undefined.

Migration Steps (Always Follow This Order)

Step 1: Find the provider (childContextTypes + getChildContext)
Step 2: Find ALL consumers (contextTypes)
Step 3: Create the context file
Step 4: Update the provider
Step 5: Update each consumer (class components → contextType, function components → useContext)
Step 6: Verify - run the app, check no legacy context warnings remain

Scan Commands

# Find all providers
grep -rn "childContextTypes\|getChildContext" src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."

# Find all consumers
grep -rn "contextTypes\s*=" src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."

# Find this.context usage (may be legacy or modern - check which)
grep -rn "this\.context\." src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."

Reference Files

  • references/single-context.md - complete migration for one context (theme, auth, etc.) with provider + class consumer + function consumer

  • references/multi-context.md - apps with multiple legacy contexts (nested providers, multiple consumers of different contexts)

  • references/context-file-template.md - the standard file structure for a new context module

Files

references/multi-context.md

Multiple Legacy Contexts - Migration Reference

Identifying Multiple Contexts

A React 16/17 codebase often has several legacy contexts used for different concerns:

# Find distinct context names used in childContextTypes
grep -rn "childContextTypes" src/ --include="*.js" --include="*.jsx" | grep -v "\.test\."
# Each hit is a separate context to migrate

Common patterns in class-heavy codebases:

  • Theme context - dark/light mode, color palette

  • Auth context - current user, login/logout functions

  • Router context - current route, navigation (if using older react-router)

  • Store context - Redux store, dispatch (if using older connect patterns)

  • Locale/i18n context - language, translation function

  • Toast/notification context - show/hide notifications


Migration Order

Migrate contexts one at a time. Each is an independent migration:

For each legacy context:
  1. Create src/contexts/[Name]Context.js
  2. Update the provider
  3. Update all consumers
  4. Run the app - verify no warning for this context
  5. Move to the next context

Do not migrate all providers first then all consumers - it leaves the app in a broken intermediate state.


Multiple Contexts in the Same Provider

Some apps combined multiple contexts in one provider component:

// Before - one provider exports multiple context values:
class AppProvider extends React.Component {
  static childContextTypes = {
    theme: PropTypes.string,
    user: PropTypes.object,
    locale: PropTypes.string,
    notifications: PropTypes.array,
  };

  getChildContext() {
    return {
      theme: this.state.theme,
      user: this.state.user,
      locale: this.state.locale,
      notifications: this.state.notifications,
    };
  }
}

Migration approach - split into separate contexts:

// src/contexts/ThemeContext.js
export const ThemeContext = React.createContext('light');

// src/contexts/AuthContext.js
export const AuthContext = React.createContext({ user: null, login: () => {}, logout: () => {} });

// src/contexts/LocaleContext.js
export const LocaleContext = React.createContext('en');

// src/contexts/NotificationContext.js
export const NotificationContext = React.createContext([]);
// AppProvider.js - now wraps with multiple providers
import { ThemeContext } from './contexts/ThemeContext';
import { AuthContext } from './contexts/AuthContext';
import { LocaleContext } from './contexts/LocaleContext';
import { NotificationContext } from './contexts/NotificationContext';

class AppProvider extends React.Component {
  render() {
    const { theme, user, locale, notifications } = this.state;
    return (
      <ThemeContext.Provider value={theme}>
        <AuthContext.Provider value={{ user, login: this.login, logout: this.logout }}>
          <LocaleContext.Provider value={locale}>
            <NotificationContext.Provider value={notifications}>
              {this.props.children}
            </NotificationContext.Provider>
          </LocaleContext.Provider>
        </AuthContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

Consumer With Multiple Contexts (Class Component)

Class components can only use ONE static contextType. For multiple, use Consumer render props or convert to a function component.

Option A - Render Props (keep as class component)
import { ThemeContext } from '../contexts/ThemeContext';
import { AuthContext } from '../contexts/AuthContext';

class UserPanel extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {(theme) => (
          <AuthContext.Consumer>
            {({ user, logout }) => (
              <div className={`panel panel-${theme}`}>
                <span>{user?.name}</span>
                <button onClick={logout}>Sign out</button>
              </div>
            )}
          </AuthContext.Consumer>
        )}
      </ThemeContext.Consumer>
    );
  }
}
Option B - Convert to Function Component (preferred)
import { useContext } from 'react';
import { ThemeContext } from '../contexts/ThemeContext';
import { AuthContext } from '../contexts/AuthContext';

function UserPanel() {
  const theme = useContext(ThemeContext);
  const { user, logout } = useContext(AuthContext);

  return (
    <div className={`panel panel-${theme}`}>
      <span>{user?.name}</span>
      <button onClick={logout}>Sign out</button>
    </div>
  );
}

If converting to a function component is out of scope for this migration sprint - use Option A. If the class component is simple (mostly just render), Option B is worth the minor rewrite.


Context File Naming Conventions

Use consistent naming across the codebase:

src/
  contexts/
    ThemeContext.js      → exports: ThemeContext, ThemeProvider (optional)
    AuthContext.js       → exports: AuthContext, AuthProvider (optional)
    LocaleContext.js     → exports: LocaleContext

Each file exports the context object. The provider can stay in its original file and just import the context.


Verification After All Contexts Migrated

# Should return zero hits for legacy context patterns
echo "=== childContextTypes ==="
grep -rn "childContextTypes" src/ --include="*.js" --include="*.jsx" | grep -v "\.test\." | wc -l

echo "=== contextTypes (legacy) ==="
grep -rn "^\s*static contextTypes\s*=\|contextTypes\.propTypes" src/ --include="*.js" | grep -v "\.test\." | wc -l

echo "=== getChildContext ==="
grep -rn "getChildContext" src/ --include="*.js" --include="*.jsx" | grep -v "\.test\." | wc -l

echo "All three should be 0"

Note: static contextType (singular) is the MODERN API - that's correct. Only contextTypes (plural) is legacy.

Requirements and compatibility

Written for: GitHub Copilot

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

First committed by
GitHub avatar of SaravananRajaramanSaravananRajaraman
Publisher
GitHub (Official)
Distributed by
GitHub
Source
github/awesome-copilot · skills/react18-legacy-context · commit 797337f
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Contributors
SaravananRajaraman

AutoGineer is not affiliated with or endorsed by SaravananRajaraman or GitHub.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download react18-legacy-context.zip