🥝

React Router v6使用時の警告とv7での変更点

2025/01/20に公開

React Router v6を使用している際にワーニングが出たので、v7での変更点を調べてまとめてみました。

React Router v7では「スプラットルート(*)」の相対パス解決方法が変更

Warningの内容:
hook.js:608 ⚠️ React Router Future Flag Warning: Relative route resolution within Splat routes is changing in v7. You can use the v7_relativeSplatPath future flag to opt-in early.
解決:
React Router v6で有効化するには、future={{ v7_relativeSplatPath: true }}のフラグを設定する。

 <BrowserRouter future={{ v7_relativeSplatPath: true }}>
 //...
</BrowserRouter>

説明:
スプラットルートとは: 未定義のパスが全てマッチする。以下のように使う。

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="script" element={<ScriptManagement />} />
    <Route path="settings" element={<Settings />} />
    <Route path="output" element={<OutputManagement />} />
    <Route path="*" element={<NotFound />} />
  </Routes>
</BrowserRouter>

NotFound の中に以下がある場合:

<Link to="about">About</Link>

v6では:
「/about」と解釈される

v7では:
「/unknown-path/about」と解釈される

React Router v7ではReact.startTransitionがデフォルトに

Warningの内容:
React Router Future Flag Warning: React Router will begin wrapping state updates in React.startTransition in v7. You can use the v7_startTransition future flag to opt-in early.
解決:
React Router v6で有効化するには、future={{ v7_startTransition: true }}のフラグを設定します。

 <BrowserRouter future={{ v7_startTransition: true }}>
 //...
</BrowserRouter>

例: React.startTransition を使わない場合(v6デフォルト)

重い状態更新が即座に処理されるため、UIがフリーズし、入力が遅れることがある。

 import React, { useState } from 'react';

const App = () => {
  const [items, setItems] = useState<number[]>([]);
  const [inputValue, setInputValue] = useState('');

  const handleAddItems = () => {
    // 重い状態更新
    const newItems = Array(10000).fill(0).map((_, i) => i);
    setItems(newItems); // UIが一時的にフリーズする可能性
  };

  return (
    <div>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)} // レスポンスが遅くなる可能性
        placeholder="Type something"
      />
      <button onClick={handleAddItems}>Add Items</button>
      <div>
        {items.map((item) => (
          <div key={item}>Item {item}</div>
        ))}
      </div>
    </div>
  );
};
export default App;

例: React.startTransition を使う場合(v7デフォルト)

React.startTransition を使用して重い状態更新を非同期的に処理するため、入力フィールドのレスポンスがスムーズになる。

import React, { useState, startTransition } from 'react';

const App = () => {
//...

  const handleAddItems = () => {
    // 非同期で重い状態更新をラップ
    startTransition(() => {
      const newItems = Array(10000).fill(0).map((_, i) => i);
      setItems(newItems); // 非同期的に実行され、UIがフリーズしにくい
    });
  };

  return (
//...
  );
};
export default App;

Discussion