# Send React Modernization to your agent
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
## Fast path
- Download the package from Yavira.
- Extract it into a folder your agent can access.
- Paste one of the prompts below and point your agent at the extracted folder.
## Suggested prompts
### New install

```text
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
```
### Upgrade existing

```text
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
```
## Machine-readable fields
```json
{
  "schemaVersion": "1.0",
  "item": {
    "slug": "react-modernization",
    "name": "React Modernization",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/wpank/react-modernization",
    "canonicalUrl": "https://clawhub.ai/wpank/react-modernization",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadUrl": "/downloads/react-modernization",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-modernization",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "packageFormat": "ZIP package",
    "primaryDoc": "SKILL.md",
    "includedAssets": [
      "README.md",
      "SKILL.md"
    ],
    "downloadMode": "redirect",
    "sourceHealth": {
      "source": "tencent",
      "slug": "react-modernization",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T23:13:10.690Z",
      "expiresAt": "2026-05-14T23:13:10.690Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-modernization",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react-modernization",
        "contentDisposition": "attachment; filename=\"react-modernization-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "react-modernization"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/react-modernization"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    }
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/react-modernization",
    "downloadUrl": "https://openagent3.xyz/downloads/react-modernization",
    "agentUrl": "https://openagent3.xyz/skills/react-modernization/agent",
    "manifestUrl": "https://openagent3.xyz/skills/react-modernization/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/react-modernization/agent.md"
  }
}
```
## Documentation

### React Modernization

Upgrade React applications from class components to hooks, adopt concurrent features, and migrate between major versions.

### WHAT

Systematic patterns for modernizing React codebases:

Class-to-hooks migration with lifecycle method mappings
React 18/19 concurrent features adoption
TypeScript migration for React components
Automated codemods for bulk refactoring
Performance optimization with modern APIs

### WHEN

Migrating class components to functional components with hooks
Upgrading React 16/17 apps to React 18/19
Adopting concurrent features (Suspense, transitions, use)
Converting HOCs and render props to custom hooks
Adding TypeScript to React projects

### KEYWORDS

react upgrade, class to hooks, useEffect, useState, react 18, react 19, concurrent, suspense, transition, codemod, migrate, modernize, functional component

### OpenClaw / Moltbot / Clawbot

npx clawhub@latest install react-modernization

### React 17 → 18 Breaking Changes

ChangeImpactMigrationNew root APIRequiredReactDOM.render → createRootAutomatic batchingBehaviorState updates batch in async code nowStrict ModeDev onlyEffects fire twice (mount/unmount/mount)Suspense on serverOptionalEnable SSR streaming

### React 18 → 19 Breaking Changes

ChangeImpactMigrationuse() hookNew APIRead promises/context in renderref as propSimplifiedNo more forwardRef neededContext as providerSimplified<Context> not <Context.Provider>Async actionsNew patternuseActionState, useOptimistic

### Lifecycle Method Mappings

// componentDidMount → useEffect with empty deps
useEffect(() => {
  fetchData()
}, [])

// componentDidUpdate → useEffect with deps
useEffect(() => {
  updateWhenIdChanges()
}, [id])

// componentWillUnmount → useEffect cleanup
useEffect(() => {
  const subscription = subscribe()
  return () => subscription.unsubscribe()
}, [])

// shouldComponentUpdate → React.memo
const Component = React.memo(({ data }) => <div>{data}</div>)

// getDerivedStateFromProps → useMemo
const derivedValue = useMemo(() => computeFrom(props), [props])

### State Migration Pattern

// BEFORE: Class with multiple state properties
class UserProfile extends React.Component {
  state = { user: null, loading: true, error: null }
  
  componentDidMount() {
    fetchUser(this.props.id)
      .then(user => this.setState({ user, loading: false }))
      .catch(error => this.setState({ error, loading: false }))
  }
  
  componentDidUpdate(prevProps) {
    if (prevProps.id !== this.props.id) {
      this.setState({ loading: true })
      fetchUser(this.props.id)
        .then(user => this.setState({ user, loading: false }))
    }
  }
  
  render() {
    const { user, loading, error } = this.state
    if (loading) return <Spinner />
    if (error) return <Error message={error.message} />
    return <Profile user={user} />
  }
}

// AFTER: Custom hook + functional component
function useUser(id: string) {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)

  useEffect(() => {
    let cancelled = false
    setLoading(true)
    
    fetchUser(id)
      .then(data => {
        if (!cancelled) {
          setUser(data)
          setLoading(false)
        }
      })
      .catch(err => {
        if (!cancelled) {
          setError(err)
          setLoading(false)
        }
      })

    return () => { cancelled = true }
  }, [id])

  return { user, loading, error }
}

function UserProfile({ id }: { id: string }) {
  const { user, loading, error } = useUser(id)
  
  if (loading) return <Spinner />
  if (error) return <Error message={error.message} />
  return <Profile user={user} />
}

### HOC to Hook Migration

// BEFORE: Higher-Order Component
function withUser(Component) {
  return function WithUser(props) {
    const [user, setUser] = useState(null)
    useEffect(() => { fetchUser().then(setUser) }, [])
    return <Component {...props} user={user} />
  }
}

const ProfileWithUser = withUser(Profile)

// AFTER: Custom hook (simpler, composable)
function useCurrentUser() {
  const [user, setUser] = useState(null)
  useEffect(() => { fetchUser().then(setUser) }, [])
  return user
}

function Profile() {
  const user = useCurrentUser()
  return user ? <div>{user.name}</div> : null
}

### New Root API (Required)

// BEFORE: React 17
import ReactDOM from 'react-dom'
ReactDOM.render(<App />, document.getElementById('root'))

// AFTER: React 18+
import { createRoot } from 'react-dom/client'
const root = createRoot(document.getElementById('root')!)
root.render(<App />)

### useTransition for Non-Urgent Updates

function SearchResults() {
  const [query, setQuery] = useState('')
  const [results, setResults] = useState([])
  const [isPending, startTransition] = useTransition()

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // Urgent: update input immediately
    setQuery(e.target.value)
    
    // Non-urgent: can be interrupted
    startTransition(() => {
      setResults(searchDatabase(e.target.value))
    })
  }

  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending ? <Spinner /> : <ResultsList data={results} />}
    </>
  )
}

### Suspense for Data Fetching

// With React 19's use() hook
function ProfilePage({ userId }: { userId: string }) {
  return (
    <Suspense fallback={<ProfileSkeleton />}>
      <ProfileDetails userId={userId} />
    </Suspense>
  )
}

function ProfileDetails({ userId }: { userId: string }) {
  // use() suspends until promise resolves
  const user = use(fetchUser(userId))
  return <h1>{user.name}</h1>
}

### React 19: use() Hook

// Read promises directly in render
function Comments({ commentsPromise }) {
  const comments = use(commentsPromise)
  return comments.map(c => <Comment key={c.id} {...c} />)
}

// Read context (simpler than useContext)
function ThemeButton() {
  const theme = use(ThemeContext)
  return <button className={theme}>Click</button>
}

### React 19: Actions

// useActionState for form submissions
function UpdateName() {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get('name'))
      if (error) return error
      redirect('/profile')
    },
    null
  )

  return (
    <form action={submitAction}>
      <input name="name" />
      <button disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  )
}

### Run Official React Codemods

# Update to new JSX transform (no React import needed)
npx codemod@latest react/19/replace-reactdom-render

# Update deprecated APIs
npx codemod@latest react/19/replace-string-ref

# Class to function components
npx codemod@latest react/19/replace-use-form-state

### Manual Search Patterns

# Find class components
rg "class \\w+ extends (React\\.)?Component" --type tsx

# Find deprecated lifecycle methods
rg "componentWillMount|componentWillReceiveProps|componentWillUpdate" --type tsx

# Find ReactDOM.render (needs migration to createRoot)
rg "ReactDOM\\.render" --type tsx

### TypeScript Migration

// Add types to functional components
interface ButtonProps {
  onClick: () => void
  children: React.ReactNode
  variant?: 'primary' | 'secondary'
}

function Button({ onClick, children, variant = 'primary' }: ButtonProps) {
  return (
    <button onClick={onClick} className={variant}>
      {children}
    </button>
  )
}

// Type event handlers
function Form() {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
  }
  
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    console.log(e.target.value)
  }

  return (
    <form onSubmit={handleSubmit}>
      <input onChange={handleChange} />
    </form>
  )
}

// Generic components
interface ListProps<T> {
  items: T[]
  renderItem: (item: T) => React.ReactNode
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return <>{items.map(renderItem)}</>
}

### Pre-Migration

Upgrade dependencies incrementally
 Review breaking changes in release notes
 Set up comprehensive test coverage
 Create feature branch

### Class → Hooks

Start with leaf components (no children)
 Convert state to useState
 Convert lifecycle to useEffect
 Extract shared logic to custom hooks
 Convert HOCs to hooks where possible

### React 18+ Upgrade

Update to createRoot API
 Test with StrictMode double-invocation
 Address hydration mismatches
 Adopt Suspense boundaries where beneficial
 Use transitions for expensive updates

### Post-Migration

Run full test suite
 Check for console warnings
 Profile performance before/after
 Document changes for team

### NEVER

Skip testing after migration
Migrate multiple components in one commit
Ignore StrictMode warnings (they reveal bugs)
Use // eslint-disable-next-line react-hooks/exhaustive-deps without understanding why
Mix class and hooks in same component
## Trust
- Source: tencent
- Verification: Indexed source record
- Publisher: wpank
- Version: 1.0.0
## Source health
- Status: healthy
- Item download looks usable.
- Yavira can redirect you to the upstream package for this item.
- Health scope: item
- Reason: direct_download_ok
- Checked at: 2026-05-07T23:13:10.690Z
- Expires at: 2026-05-14T23:13:10.690Z
- Recommended action: Download for OpenClaw
## Links
- [Detail page](https://openagent3.xyz/skills/react-modernization)
- [Send to Agent page](https://openagent3.xyz/skills/react-modernization/agent)
- [JSON manifest](https://openagent3.xyz/skills/react-modernization/agent.json)
- [Markdown brief](https://openagent3.xyz/skills/react-modernization/agent.md)
- [Download page](https://openagent3.xyz/downloads/react-modernization)