ふかしぎのReactさんぷるず

React Router v6 の機能 - Reactさんぷるず

最終更新 2022/01/26
React Router v6 の機能についての説明です。初心者向けです。
説明で使用しているReactは 17.0.2 です。
説明で使用しているReact Router v6は 6.2.1 です。

BrowserRouter

ブラウザーでReact Routerを実行するために使用します。
何も考えずおおもとをこれで囲んでください。
この中がReact Routerの領域になります。
<Link>や<Route>などはこの中に無ければいけません。
ReactDOM.render(
  <BrowserRouter>
    ここにLinkやNavLinkやRoutesやRouteを書いていきます。
  </BrowserRouter>
, document.getElementById('content')
);
ブラウザーのURLアドレス欄を変更するのはLinkで行います。
変更したURLの描画はRouteで行います。

basename

basenameで基準のパスを設定できます。
<BrowserRouter basename="/react/router/sample01/">
のように記述します。
これにより中に記述されたLinkなどのパスは自動的にbasenameを加えたものが処理されます。
https://code.fukasigi.net/react/router/sample01/
<BrowserRouter basename="/react/router/sample01/">
  <Link to="/">Home</Link>
  <Link to="Link1">Link1</Link>
</BrowserRouter>
上の例だと
https://code.fukasigi.net/react/router/sample01/
<BrowserRouter>
  <Link to="/react/router/sample01/">Home</Link>
  <Link to="/react/router/sample01/Link1">Link1</Link>
</BrowserRouter>
と同じ意味になります。
何も設定しないとそのドメインのルートが基準になります。

Link

Linkはブラウザーのアドレス欄を変更する機能です。
実際の動きはサンプル1とそのソースを見てください。
A要素と似たような感じになりHTMLのリンクを生成しそれをクリックしたらURLが変わる仕組みになります。
ブラウザーの履歴に入るのでブラウザーの戻るボタンを押すと直前のURLに戻ることができます。

toで変更するアドレスを指定

<Link to="">が書き方になります。
toにブラウザーのアドレス欄に表示したいパスを記述します。
パスは絶対パスと相対パスのどちらでも使えます。
相対パスにした場合はレンダリングした場所が基準になります。
/Link1/Link2/でレンダリングしたLinkの場合../で一つ上に行くと/Link1/に移動します。
例えば現在のアドレスが/Link1/Link2/Link3/だとしても/Link1/Link2/でレンダリングしたLinkの場合../で一つ上に行くと/Link1/に移動します。/Link1/Link2/にはなりません。
../というリンクをレンダリングした時点、つまり/Link1/Link2/が基準になります。
レンダリングした後にアドレスが/Link1/Link2/Link3/に変わっても相対パスの基準は変わりません。
ブラウザーのアドレス欄は/Link1/Link2/Link3/になっているんだから../でクリックしたら/Link1/Link2/になるんじゃないの?と思ってしまいそうですがそうはなりません。

replaceで履歴を残さない

クリックしたリンクはブラウザーの履歴に保存されます。
そのためブラウザーの戻るボタンを押したときに順番にリンクの表示が戻っていきます。
直前のアドレスを履歴に残す必要がない場合はreplaceをfalseにすることにより戻るボタンで直前のアドレスに戻れなくなります。
<Link to="" replace="false">と記述します。
<Link to="" replace="false">

reloadDocumentで再描画(リロード)

LinkはA要素と違い全体を読み込みません。全体を再読み込み(リロード)したい場合はreloadDocumentをtrueにします。
<Link to="" reloadDocument="true">と記述します。
これは<a href="">と同じ動きになります。
<Link to="" reloadDocument="true">
実際の動きをサンプル1で確認する

NavLink

NavLinkはLinkに押したリンクをわかりやすくする機能を付け加えたものです。
この機能でクリックしたリンクを強調表示したりしてわかりやすくします。
ブラウザーの履歴に入るのでブラウザーの戻るボタンを押すと直前のURLに戻ることができます。

isActive

クリックしたものはisActiveがtrueになります。それを判別してCSSで表示を変化させる仕組みになります。
isActiveが使えるのはclassNameとstyleとchildrenになります。

className

class名でクリックしたリンクを強調します。
<NavLink to="" className={({ isActive }) => isActive ? activeClassName : undefined}>ナビリンク</NavLink>
のように使います。
実際の動きはサンプル2とそのソースを見てください。
activeClassNameは"activeCSS"という文字列の入った変数です。activeCSSは文字を赤色太字で大きくするCSSを<style>で定義しています。
classNameはHTMLの各要素のclass属性でCSSの名前を設定するときに使用します。
基本はclassName="TukuttaCssClassNoNamae"です。
className={ほにゃらら}と中括弧で囲むことにより中にJavaScriptを書けるようになります。
アロー関数や三項演算子は初心者にはわかりづらいので色々な書き方のサンプルを書きます。
この1~7は全て同じ意味になります。
1.変数ではなくCSSの名前を直接書く
className={
  ({ isActive }) => isActive ? "activeCSS" : undefined
}
2.CSSの名前を変数で設定する。
className={
  ({ isActive }) => isActive ? activeClassName : undefined
}
3.isActiveを直接渡すのではなくpropsで渡す。(渡す変数はpropsひとつなので括弧を省略)
className={
   props  => props.isActive ? activeClassName : undefined
}
4.isActiveを直接渡すのではなくpropsで渡す。(propsの括弧を省略しない)
className={
  ( props ) => props.isActive ? activeClassName : undefined
}
5.アロー関数の中括弧を省略しない。その場合はreturnが必要になる。
className={
  ( props ) => {
    return  props.isActive ? activeClassName : undefined;
  }
}
6.さらにアロー関数内を省略形の三項演算子ではなくif文で書く
className={
  ( props ) => {
    let rtnCssName:string = '';
    if (props.isActive == true) {
      rtnCssName = activeClassName;
    } else {
      rtnCssName = undefined;
    };
    return rtnCssName;
  }
}
7.さらにアロー関数ではなく普通の関数で書く
className={
  function( props ) {
    let rtnCssName:string = '';
    if (props.isActive == true) {
      rtnCssName = activeClassName;
    } else {
      rtnCssName = undefined;
    };
    return rtnCssName;
  }
}
実際の動きをサンプル2で確認する

style

CSSでクリックしたリンクを強調します。
<NavLink to="" style={({ isActive }) => isActive ? activeStyle : undefined}>ナビリンク</NavLink>
のように使います。
実際の動きはサンプル3とそのソースを見てください。
activeStyle は文字を青色太字で大きくするCSSを記述した変数です。
styleはHTMLの各要素のstyle属性でCSSを設定するときに使用します。
基本はstyle={{CSSwoKaku}}です。
classNameの方は文字列型を記述できますすがstyleは文字列型を記述できません。
そのためstyle="CSSwoKaku"はエラーになります。
The above error occurred in the <a> component
Uncaught Error: The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.
うっかり文字列型にしていると上記のようなエラーになります。
基本はstyle={{fontWeight: "bold"}}のような記述です。
注意してくださいHTMLのCSSと記述が少し異なります。
font-weight: bold; ではなく fontWeight: "bold" になります。
基本は名称のハイフンを取り除き次の一文字目を大文字に、そして値をダブルクォートで囲むと覚えてください。
設定できるのはReactのCSSPropertiesになります。
style={ほにゃらら}と中括弧で囲むことにより中にJavaScriptを書けるようになります。
そしてその中にReactのCSSPropertiesを記述する形になります。そのため中括弧が二重になっています。
アロー関数や三項演算子は初心者にはわかりづらいので色々な書き方のサンプルを書きます。
この1~7は全て同じ意味になります。
1.変数ではなくCSSを直接書く
style={
  ({ isActive }) => isActive ? {fontWeight: "bold", color: "blue", fontSize: "2rem"} : undefined
}
2.CSSを変数で設定する。
style={
  ({ isActive }) => isActive ? activeStyle  : undefined
}
3.isActiveを直接渡すのではなくpropsで渡す。(渡す変数はpropsひとつなので括弧を省略)
style={
   props  => props.isActive ? activeStyle  : undefined
}
4.isActiveを直接渡すのではなくpropsで渡す。(propsの括弧を省略しない)
style={
  ( props ) => props.isActive ? activeStyle  : undefined
}
5.アロー関数の中括弧を省略しない。その場合はreturnが必要になる。
style={
  ( props ) => {
    return  props.isActive ? activeStyle  : undefined;
  }
}
6.さらにアロー関数内を省略形の三項演算子ではなくif文で書く
style={
  ( props ) => {
    let rtnCssName:string = '';
    if (props.isActive == true) {
      rtnCssName = activeStyle ;
    } else {
      rtnCssName = undefined;
    };
    return rtnCssName;
  }
}
7.さらにアロー関数ではなく普通の関数で書く
style={
  function( props ) {
    let rtnCssName:string = '';
    if (props.isActive == true) {
      rtnCssName = activeStyle ;
    } else {
      rtnCssName = undefined;
    };
    return rtnCssName;
  }
}
実際の動きをサンプル3で確認する

end

部分一致の禁止
実際の動きはサンプル4とそのソースを見てください。
NavLinkはtoが先頭から部分一致すればisActiveをtrueにしてしまいます。
つまり
to="Link1"と
to="Link1/subLink1"があった場合
下の方をクリックすると上まで強調表示されてしまいます。
それを回避するのがendです。
to="Link1"にendを付け加えると"Link1"の時だけisActiveをtrueにします。
<NavLink to="Link1" end style={({ isActive }) => isActive ? activeStyle : undefined}>ナビリンク</NavLink>
endはend={true}を省略しているだけなので
<NavLink to="Link1" end={true} style={({ isActive }) => isActive ? activeStyle : undefined}>ナビリンク</NavLink>
と書いても同じ意味になります。
実際の動きをサンプル4で確認する

caseSensitive

大文字小文字の区別
実際の動きはサンプル5とそのソースを見てください。
通常は大文字小文字が区別されません。デフォルトはfalseです。
to="Link1"と
to="LINK1"があった場合
両方とも強調表示されます。
大文字小文字の区別をしたい場合はcaseSensitiveを設定します。
to="Link1"にcaseSensitiveを付け加えると"Link1"の時だけisActiveをtrueにし、"LINK1"は対象外になります。
<NavLink to="Link1" caseSensitive style={({ isActive }) => isActive ? activeStyle : undefined}>ナビリンク</NavLink>
caseSensitiveはcaseSensitive={true}を省略しているだけなので
<NavLink to="Link1" caseSensitive={true} style={({ isActive }) => isActive ? activeStyle : undefined}>ナビリンク</NavLink>
と書いても同じ意味になります。
実際の動きをサンプル5で確認する

children

リンクの表示を直接記述するのではなくReactNodeで指定できます。
実際の動きはサンプル6とそのソースを見てください。
children={Link1}のように使います。
childrenにはisActiveも使えます。
<NavLink to="Link1" children={({ isActive }) => isActive ? DIV1() : DIV2()} />
のように使います。
注意してください!
コンポーネント自体ではなく実行した結果(render)を渡さなければいけません。
<NavLink to="Link1" children={({ isActive }) => isActive ? DIV1 : DIV2} />
とかっこなしにすると
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
と怒られます。
実際の動きをサンプル6で確認する

Navigate

useNavigateを使った方がいいので省略

RoutesとRoute

LinkやNavLinkでURLを変更しパスを変更する。そしてRoutesとRouteがそのパスに一致するものを表示する。という仕組みです。
実際の動きはサンプル11とそのソースを見てください。
おおもとをRoutesで囲みその下にRouteを書きます。
<BrowserRouter>
  <Routes>
    <Route path='/react/router/sample11/Home' element={<HomeDIV />} />
    <Route path='/react/router/sample11/Link1' element={<Link1DIV />} />
    <Route path='/react/router/sample11/Link2' element={<Link2DIV />} />
  </Routes>
</BrowserRouter>
この場合URLがhttps://code.fukasigi.net/react/router/sample11/HomeになったらHomeDIVを表示
https://code.fukasigi.net/react/router/sample11/Link1になったらLink1DIVを表示
https://code.fukasigi.net/react/router/sample11/Link2になったらLink2DIVを表示
というようになります。
いちいちフルパスを書くのが面倒な場合はBrowserRouterにbasenameで基準のパスを決めると記述が楽になります。
<BrowserRouter basename="/react/router/sample11/">
  <Routes>
    <Route path='/' element={<HomeDIV />} />
    <Route path='Link1' element={<Link1DIV />} />
    <Route path='Link2' element={<Link2DIV />} />
  </Routes>
</BrowserRouter>
実際の動きをサンプル11で確認する

location

locationを変更する。
実際の動きはサンプル12とそのソースを見てください。
Routesはlocationによって一致するRouteを判別して表示します。
locationを設定することにより上書きすることができます。
locationを設定しなかった場合現在のパスがlocationになります。
<Routes location="/Link1">
  <Route path='/' element={<Home />} />
  <Route path='Link1' element={<Link1 />} />
</Routes>
これにより現在のブラウザーのURLがどのようなパスになっていても/Link1として処理されLink1の内容が表示されます。
たとえHomeを押してブラウザー上のURLが変わろうが内部的にはLink1になるのでLink1が表示されます。
実際の動きをサンプル12で確認する

Outlet

Routeは入れ子にできます。
通常は入れ子の内容は表示されません。
入れ子の内容も表示したい場合は親RouteにOutletを設定し子Routeの要素をそのOutletにレンダリングします。
実際の動きはサンプル8とそのソースを見てください。
<Routes>
  <Route path='/' element={<Home />}>
    <Route path='Link1' element={<Link1 />} >
      <Route path='Link2' element={<Link2 />}>
        <Route path='Link3' element={<Link3 />} />
      </Route>
    </Route>
  </Route>
</Routes>
この場合だとLink1は/Link1というパスの時に一致します。
Link2は/Link1/Link2というパスの時に一致します。
Link3は/Link1/Link2/Link3というパスの時に一致します。
Routeを入れ子にした場合は直前の親Routeが基準パスとなります。
実際の動きをサンプル8で確認する

contextとuseOutletContext

Outletで子RouteにuseStateの情報を渡すことができます。
実際の動きはサンプル9とそのソースを見てください。
useStateが親Routeと子Routeで共有されるので子Routeで親のuseStateを扱えることになります。
Outletにcontextを設定して子Routeに受け渡します。
<Outlet context={[homeCount, setCount]} />
のように使います。
渡された子Route側では
const [oyaNoCount, setOyaNoCount] = useOutletContext();
のようにuseOutletContextを使いOutlet contextで送られてきた情報を設定します。
あとはuseStateと同じように使用すれば親側にも変更した情報が反映されます。
実際の動きをサンプル9で確認する

React 目次

最初に現在のReactについて
世界一シンプルなサンプル
React Router v6
React Router v6 API
MUI v5
sxの解説
マテリアルアイコンの解説
Autocomplete
Avatar
AvatarGroup
Badge
Button
ButtonGroup
Checkbox
Chip
Collapse
Divider
Floating Action Button(Fab)
Fade
FormControlLabel
Grow
Icon
List
ListItem
ListItemAvatar
ListItemButton
ListItemIcon
ListItemSecondaryAction
ListItemText
ListSubheader
Radio
RadioGroup
Rating
Select
Slide
Slider
Switch
TextField
ToggleButton
ToggleButtonGroup
Zoom
エラー対処
HTMl select
戻る

全体目次