React Modernization

作者 wshobson46891e7e60da無授權條款收錄於 2026年10月8日更新於 2026年10月8日

Upgrade React applications to latest versions, migrate from class components to hooks, and adopt concurrent features. Use when modernizing React codebases, migrating to React Hooks, or upgrading to latest React versions.

AI 產生的概覽

指導升級 React 應用程式、將類別元件遷移到 Hooks,並採用 React 18 並行功能。

功能
此技能提供用於現代化 React 程式碼庫的指示與程式碼範例。內容涵蓋從 React 16 到 18 的版本升級路徑、將類別元件與生命週期方法轉換為 Hooks,以及採用新根 API、自動批次處理、轉場與 Suspense 等並行功能。它也指向一個包含更多模式與範本的參考檔案。
適用情境
適用於將 React 應用程式升級到較新版本、把類別元件遷移為使用 Hooks 的函式元件,或採用 React 18 並行功能時。也適合重構狀態管理模式以及遷移到 TypeScript。
執行需求
無需指令碼或特殊工具,僅為指示性內容。需要閱讀參考檔案 references/details.md 以取得完整模式庫。

React Modernization

Master React version upgrades, class to hooks migration, concurrent features adoption, and codemods for automated transformation.

When to Use This Skill

  • Upgrading React applications to latest versions
  • Migrating class components to functional components with hooks
  • Adopting concurrent React features (Suspense, transitions)
  • Applying codemods for automated refactoring
  • Modernizing state management patterns
  • Updating to TypeScript
  • Improving performance with React 18+ features

Version Upgrade Path

React 16 → 17 → 18

Breaking Changes by Version:

React 17:

  • Event delegation changes
  • No event pooling
  • Effect cleanup timing
  • JSX transform (no React import needed)

React 18:

  • Automatic batching
  • Concurrent rendering
  • Strict Mode changes (double invocation)
  • New root API
  • Suspense on server

Class to Hooks Migration

State Management

javascript
// Before: Class componentclass Counter extends React.Component {  constructor(props) {    super(props);    this.state = {      count: 0,      name: "",    };  }
  increment = () => {    this.setState({ count: this.state.count + 1 });  };
  render() {    return (      <div>        <p>Count: {this.state.count}</p>        <button onClick={this.increment}>Increment</button>      </div>    );  }}
// After: Functional component with hooksfunction Counter() {  const [count, setCount] = useState(0);  const [name, setName] = useState("");
  const increment = () => {    setCount(count + 1);  };
  return (    <div>      <p>Count: {count}</p>      <button onClick={increment}>Increment</button>    </div>  );}

Lifecycle Methods to Hooks

javascript
// Before: Lifecycle methodsclass DataFetcher extends React.Component {  state = { data: null, loading: true };
  componentDidMount() {    this.fetchData();  }
  componentDidUpdate(prevProps) {    if (prevProps.id !== this.props.id) {      this.fetchData();    }  }
  componentWillUnmount() {    this.cancelRequest();  }
  fetchData = async () => {    const data = await fetch(`/api/${this.props.id}`);    this.setState({ data, loading: false });  };
  cancelRequest = () => {    // Cleanup  };
  render() {    if (this.state.loading) return <div>Loading...</div>;    return <div>{this.state.data}</div>;  }}
// After: useEffect hookfunction DataFetcher({ id }) {  const [data, setData] = useState(null);  const [loading, setLoading] = useState(true);
  useEffect(() => {    let cancelled = false;
    const fetchData = async () => {      try {        const response = await fetch(`/api/${id}`);        const result = await response.json();
        if (!cancelled) {          setData(result);          setLoading(false);        }      } catch (error) {        if (!cancelled) {          console.error(error);        }      }    };
    fetchData();
    // Cleanup function    return () => {      cancelled = true;    };  }, [id]); // Re-run when id changes
  if (loading) return <div>Loading...</div>;  return <div>{data}</div>;}

Context and HOCs to Hooks

javascript
// Before: Context consumer and HOCconst ThemeContext = React.createContext();
class ThemedButton extends React.Component {  static contextType = ThemeContext;
  render() {    return (      <button style={{ background: this.context.theme }}>        {this.props.children}      </button>    );  }}
// After: useContext hookfunction ThemedButton({ children }) {  const { theme } = useContext(ThemeContext);
  return <button style={{ background: theme }}>{children}</button>;}
// Before: HOC for data fetchingfunction withUser(Component) {  return class extends React.Component {    state = { user: null };
    componentDidMount() {      fetchUser().then((user) => this.setState({ user }));    }
    render() {      return <Component {...this.props} user={this.state.user} />;    }  };}
// After: Custom hookfunction useUser() {  const [user, setUser] = useState(null);
  useEffect(() => {    fetchUser().then(setUser);  }, []);
  return user;}
function UserProfile() {  const user = useUser();  if (!user) return <div>Loading...</div>;  return <div>{user.name}</div>;}

React 18 Concurrent Features

New Root API

javascript
// Before: React 17import ReactDOM from "react-dom";
ReactDOM.render(<App />, document.getElementById("root"));
// After: React 18import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));root.render(<App />);

Automatic Batching

javascript
// React 18: All updates are batchedfunction handleClick() {  setCount((c) => c + 1);  setFlag((f) => !f);  // Only one re-render (batched)}
// Even in async:setTimeout(() => {  setCount((c) => c + 1);  setFlag((f) => !f);  // Still batched in React 18!}, 1000);
// Opt out if neededimport { flushSync } from "react-dom";
flushSync(() => {  setCount((c) => c + 1);});// Re-render happens heresetFlag((f) => !f);// Another re-render

Transitions

javascript
import { useState, useTransition } from "react";
function SearchResults() {  const [query, setQuery] = useState("");  const [results, setResults] = useState([]);  const [isPending, startTransition] = useTransition();
  const handleChange = (e) => {    // Urgent: Update input immediately    setQuery(e.target.value);
    // Non-urgent: Update results (can be interrupted)    startTransition(() => {      setResults(searchResults(e.target.value));    });  };
  return (    <>      <input value={query} onChange={handleChange} />      {isPending && <Spinner />}      <Results data={results} />    </>  );}

Suspense for Data Fetching

javascript
import { Suspense } from "react";
// Resource-based data fetching (with React 18)const resource = fetchProfileData();
function ProfilePage() {  return (    <Suspense fallback={<Loading />}>      <ProfileDetails />      <Suspense fallback={<Loading />}>        <ProfileTimeline />      </Suspense>    </Suspense>  );}
function ProfileDetails() {  // This will suspend if data not ready  const user = resource.user.read();  return <h1>{user.name}</h1>;}
function ProfileTimeline() {  const posts = resource.posts.read();  return <Timeline posts={posts} />;}

Additional patterns and templates

More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.

來源與署名

來源:wshobson/agents位於plugins/framework-migration/skills/react-modernization提交46891e7

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架