æçš¿è
@ pshrmnâ¬
ãªãªãžãã«èšäº â¬
èªæžæé ïŒ
10åReact Router v4ã¯ã人æ°ã®ããReactã¢ããªã³ã®åèšèšãããããŒãžã§ã³ã§ãã 以åã®ããŒãžã§ã³ã®ãã©ãããã©ãŒã äŸåã®ã«ãŒãæ§æã¯åé€ããããã¹ãŠãã·ã³ãã«ãªã³ã³ããŒãã³ãã«ãªããŸããã
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãReact Routerã§Webãµã€ããæ§ç¯ããããã«å¿
èŠãªãã¹ãŠãã«ããŒããŠããŸãã å°å
ã®ã¹ããŒãããŒã ã®ãµã€ããäœæããŸãã
ãã¢ãèŠããã§ããïŒ
èšçœ®
React Router v4ã¯3ã€ã®ããã±ãŒãžã«åå²ãããŸããã
react-router
router-dom
react-router-native
react-routerã¯ã2ã€ã®ç°å¢ïŒBrowserããã³react-nativeïŒã§äœæ¥ããããã®åºæ¬çãªæ©èœãšã³ã³ããŒãã³ããæäŸããŸã
ãã©ãŠã¶ã«è¡šç€ºããããµã€ããäœæããã®ã§ã
react-router-dom䜿çš
react-router-domå¿
èŠããããŸãã
react-router-domã¯ãã¹ãŠã®æ©èœã
react-routerãããšã¯ã¹ããŒãããããã
react-router-domãã€ã³ã¹ããŒã«
react-router-domã ãã§ãã
npm install --save react-router-dom
ã«ãŒã¿ãŒ
ãããžã§ã¯ããéå§ãããšãã䜿çšããã«ãŒã¿ãŒã®ã¿ã€ããæ±ºå®ããå¿
èŠããããŸãã ãã©ãŠã¶ãŒãããžã§ã¯ãã«ã¯ã
BrowserRouterããã³
HashRouterã³ã³ããŒãã³ãããããŸãã
BrowserRouterãµãŒããŒã§åçãªã¯ãšã¹ããåŠçãããšãã«äœ¿çšããéçWebãµã€ããããå Žåã¯
HashRouterã䜿çšããå¿
èŠããããŸãã
éåžžã
BrowserRouterã䜿çšããããšãã
BrowserRouterãŸããããµã€ããéçãµãŒããŒïŒ
githubããŒãžãšããŠã®ç¿»èš³ãã ïŒã«ããå Žåã¯ã
HashRouterã䜿çšããããšãåé¡ã®è¯ã解決çã§ãã
ãã®ãããžã§ã¯ãã§ã¯ããã¯ãšã³ãã䜿çšããããã
BrowserRouterã䜿çšã
BrowserRouter ã
æŽå²-æŽå²
åã«ãŒã¿ãŒã¯ãçŸåšã®å Žæ[1]ãžã®ãã¹ãæ ŒçŽãã
historyãªããžã§ã¯ããäœæãããã¹ã®å€æŽãçºçãããšãã«ãµã€ãã€ã³ã¿ãŒãã§ã€ã¹ãåæç»ããŸãã
React Routerã§æäŸãããæ®ãã®æ©èœã¯ãã³ã³ããã¹ããä»ãã
historyãªããžã§ã¯ãã®å¯çšæ§ã«äŸåããŠãããããã«ãŒã¿ãŒã³ã³ããŒãã³ãå
ã§ã¬ã³ããªã³ã°ããå¿
èŠããããŸãã
泚ïŒç¥å
ãšããŠã«ãŒã¿ãŒã³ã³ããŒãã³ããæããªãReactã«ãŒã¿ãŒã³ã³ããŒãã³ãã¯ãã³ã³ããã¹ããå©çšã§ããªãããæ©èœããŸããã
ã«ãŒã¿ãŒã®ã¬ã³ããªã³ã°
Routerã³ã³ããŒãã³ãã¯ãåãšããŠ1ã€ã®èŠçŽ ã®ã¿ãæ³å®ããŠããŸãã ãã®æ¡ä»¶äžã§äœæ¥ããã«ã¯ãã¢ããªã±ãŒã·ã§ã³å
šäœãã¬ã³ããªã³ã°ãã<App />ã³ã³ããŒãã³ããäœæãããšäŸ¿å©ã§ãïŒããã¯ãµãŒããŒã¬ã³ããªã³ã°ã«ãéèŠã§ãïŒã
import { BrowserRouter } from 'react-router-dom'; ReactDOM.render(( <BrowserRouter> <App /> </BrowserRouter> ), document.getElementById('root'))
ã¢ããªã³ã³ããŒãã³ã
ã¢ããªã±ãŒã·ã§ã³ã¯ã2ã€ã®éšåã«åå²ãã
<App/>ã³ã³ããŒãã³ãã§å§ãŸããŸãã
<Header/>ã«ã¯ããã²ãŒã·ã§ã³ãªã³ã¯ãå«ãŸãã
<Main/>ã«ã¯ã«ãŒãã®ã³ã³ãã³ããå«ãŸããŸãã
ã«ãŒã
<Route/>ã³ã³ããŒãã³ãã¯ãReact Routerã®äž»èŠãªæ§æèŠçŽ ã§ãã URLã®ãã¹åã«å¿ããŠèŠçŽ ãã¬ã³ããªã³ã°ããå¿
èŠãããå Žåã¯ã
<Route/>ã³ã³ããŒãã³ãã䜿çšããå¿
èŠããããŸã
ãã¹-ãã¹
<Route />ã¯ãç¹å®ã®ãã¹ãèšè¿°ããlocation.pathnameã«ãããããå°éå
·ãšããŠ
pathãåã
path ã
<Route path='/roster'/>
äžèšã®äŸã§ã¯ã
<Route/>ã¯/ roster [2]ã§å§ãŸãlocation.pathnameãšäžèŽããŸãã çŸåšã®location.pathnameãpropãã¹ã«ããžãã£ãã«ãããããããšãã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããããããäžèŽããªãå ŽåãRouteã¯äœãã¬ã³ããªã³ã°ããŸãã[3]ã
<Route path='/roster'/>
泚ïŒãã¹ã«é¢ããŠã¯ãReact Routerã¯ãã¡ã€ã³ã®ãªããã¹ã®ã¿ãèæ
®ããŸãã ããã¯ãã¢ãã¬ã¹ã§æ¬¡ã®ããšãæå³ããŸãã
http://www.example.com/my-projects/one?extra=false
React Routerã¯
/my-projects/oneã®ã¿ã衚瀺ããŸã
ãã¹ãããã³ã°
npm
path-to-regexpããã±ãŒãžã¯ãpropãã¹ãæ£èŠè¡šçŸã«ã³ã³ãã€ã«ããlocation.pathnameãšç
§åããŸãã ãã¹è¡ã«ã¯ãããã§èª¬æãããããè€éãªæžåŒèšå®ãªãã·ã§ã³ããããŸãã
ããã¥ã¡ã³ããèªãããšãã§ã
ãŸã ã
ãã¹ãäžèŽãã
match ãããããã£ãå«ã
matchãªããžã§ã¯ããäœæãããŸãã
- url-çŸåšã®location.pathnameã®ãããã³ã°ãããéšå
- path -Routeã³ã³ããŒãã³ãã®ãã¹
- isExact-ã«ãŒãã®ãã¹=== location.pathname
- params-ãªããžã§ã¯ãã«ã¯ãpath-to-regexpã¢ãžã¥ãŒã«ãè¿ããã¹ããã®å€ãå«ãŸããŸã
æ³šïŒ ã«ãŒããã¹ã¿ãŒã§éãã§ãäžèŽãªããžã§ã¯ããã©ã®ããã«äœæããããã確èªã§ããŸãã
泚ïŒã«ãŒãã®ãã¹ã¯çµ¶å¯Ÿãã¹ã§ãªããã°ãªããŸãã[4]ã
ã«ãŒããäœæãã
Routeã³ã³ããŒãã³ãã¯ã«ãŒã¿ãŒå
ã®ã©ãã«ã§ãé
眮ã§ããŸãããåãå Žæã«äœãã¬ã³ããªã³ã°ããããæ±ºå®ããå¿
èŠãããå ŽåããããŸãã ãã®å Žåãã«ãŒãã°ã«ãŒãåã³ã³ããŒãã³ã-
<Switch/>ãŸãã
<Switch/>ã¯åã³ã³ããŒãã³ããå埩åŠçããlocation.pathnameã«äžèŽããæåã®ã³ã³ããŒãã³ãã®ã¿ãã¬ã³ããªã³ã°ããŸãã
ç§ãã¡ã®ãŠã§ããµã€ãã«ã¯ããããããããã¹ããããŸãïŒ
- / -ããŒã ããŒãž
- /åç°¿ -ã³ãã³ãããŒãž
- /åç°¿/ïŒçªå· -çªå·ã«ãããã¬ãŒã€ãŒãããã£ãŒã«ããŒãž
- /ã¹ã±ãžã¥ãŒã« -ããŒã ã¹ã±ãžã¥ãŒã«
ã¢ããªã±ãŒã·ã§ã³ã§ãã¹ããããããããã«å¿
èŠãªããšã¯ããããããpropãã¹ã䜿çšããŠRouteã³ã³ããŒãã³ããäœæããããšã ãã§ãã
<Switch> <Route exact path='/' component={Home}/> {/* /roster /roster/:number /roster */} <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch>
Routeã³ã³ããŒãã³ãã¯äœãã¬ã³ããªã³ã°ããŸããïŒ
ã«ãŒãã«ã¯ãå°éå
·ã®ãã¹ãlocation.pathnameãšäžèŽãããããšã§ã¬ã³ããªã³ã°ããæ¹æ³ã説æãã3ã€ã®å°éå
·ããããå°éå
·ã®1ã€ã ããRouteã§è¡šãå¿
èŠããããŸãã
- component -Reactã³ã³ããŒãã³ãã ã«ãŒãããã¹ã«äžèŽãããšãæž¡ãããã³ã³ããŒãã³ããè¿ããŸãïŒReact.createElement颿°ã䜿çšïŒã
- renderã¯ãReactèŠçŽ ãè¿ãå¿
èŠããã颿°ã§ãã ãã¹å
ã®äžèŽãæºãããããšãã«åŒã³åºãããŸãã ã¬ã³ããªã³ã°ã¯ã³ã³ããŒãã³ãã«éåžžã«äŒŒãŠããŸãããã€ã³ã©ã€ã³ã¬ã³ããªã³ã°ãšå¿
èŠãªpropsèŠçŽ ã®çœ®æã«äœ¿çšãããŸã[5]ã
- children-åã®2ã€ã®å°éå
·ãšã¯ç°ãªãããã¹ãããããããŠãããã©ããã«é¢ä¿ãªããåã¯åžžã«è¡šç€ºãããŸãã
<Route path='/page' component={Page} /> const extraProps = { color: 'red' } <Route path='/page' render={(props) => ( <Page {...props} data={extraProps}/> )}/> <Route path='/page' children={(props) => ( props.match ? <Page {...props}/> : <EmptyPage {...props}/> )}/>
äžè¬çãªç¶æ³ã§ã¯ãã³ã³ããŒãã³ãã䜿çšãããã¬ã³ããªã³ã°ããŸãã children propã¯äœ¿çšã§ããŸãããpathãlocation.pathnameãšäžèŽããªãå Žåã¯äœãããªãããšãæåã§ãã
ã¬ã³ããªã³ã°ããã
Routeã¯ãããã€ãã®å°éå
·ãæž¡ãããŸãã
match -
pathã
location.pathname ã
locationãªããžã§ã¯ã[6]ããã³
historyãªããžã§ã¯ãïŒã«ãŒãèªäœã«ãã£ãŠäœæïŒ[7]ã«ããããããªããžã§ã¯ãã
ã¡ã€ã³
次ã«ãã«ãŒã¿ãŒã®åºæ¬æ§é ã«ã€ããŠèª¬æããŸãã ã«ãŒãããããã³ã°ããã ãã§ãã ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ã
<Main/>ã³ã³ããŒãã³ãå
ã§
<Switch/>ã³ã³ããŒãã³ããš
<Route/>ã³ã³ããŒãã³ãã䜿çšããå
éšã§
pathäžèŽããçæãããHTMLãé
眮ããŸãã
<Main/>ããŒãïŒããŒãïŒã®DOM
import { Switch, Route } from 'react-router-dom' const Main = () => ( <main> <Switch> <Route exact path='/' component={Home}/> <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch> </main> )
泚ïŒã¡ã€ã³ããŒãž
ã® Routeã«ã¯prop
exactãå«ãŸããŠããããããã¹ãå³å¯ã«æ¯èŒãããŸãã
ç¶æ¿ãããã«ãŒã
ãã¬ãŒã€ãŒãããã¡ã€ã«
/roster/:number <Switch/>å«ãŸããŠããŸããã 代ããã«ããã¹ã
/rosterå§ãŸããã³ã«ã¬ã³ããªã³ã°ããã
<Roster/>ã³ã³ããŒãã³ãã«ãã£ãŠã¬ã³ããªã³ã°ãããŸãã
Rosterã³ã³ããŒãã³ãã§ã¯ã2ã€ã®ãã¹ã®ã³ã³ããŒãã³ããäœæããŸãã
- /åç°¿ -æ£ç¢ºãªå°éå
·ä»ã
- / roster /ïŒnumber-ãã®ã«ãŒãã¯ã/ rosterã®åŸã«ãã£ããããããã¹ãã©ã¡ãŒã¿ãŒã䜿çšããŸã
const Roster = () => ( <Switch> <Route exact path='/roster' component={FullRoster}/> <Route path='/roster/:number' component={Player}/> </Switch> )
å
±éã³ã³ããŒãã³ããæã€ã«ãŒããã°ã«ãŒãåãããšäŸ¿å©ã§ããããã«ããã芪ã«ãŒããç°¡çŽ åãããè€æ°ã®ã«ãŒãã«é¢é£ããã³ã³ãã³ãã衚瀺ã§ããŸãã
ããšãã°ã
<Roster/>ã¯ã
/rosterã§å§ãŸããã¹ãŠã®ã«ãŒãã«è¡šç€ºãããããããŒã§ã¬ã³ããªã³ã°ã§ããŸãã
const Roster = () => ( <div> <h2>This is a roster page!</h2> <Switch> <Route exact path='/roster' component={FullRoster}/> <Route path='/roster/:number' component={Player}/> </Switch> </div> )
ãã¹å
ã®ãã©ã¡ãŒã¿ãŒ
倿°ã䜿çšããŠäœããã®æ
å ±ãååŸããå¿
èŠãããå ŽåããããŸãã ããšãã°ããã¬ãŒã€ãŒçªå·ãååŸããå¿
èŠããããã¬ãŒã€ãŒãããã¡ã€ã«ã«ãŒãã ãããè¡ãã«ã¯ããã©ã¡ãŒã¿ãæ¯æ±
path远å ããŸãã
:number /roster/:numberè¡
:numberéšåã«
/roster/:numberã
match.params.numberãšã
/roster/åŸã®
pathéšåã倿°ãšããŠåä¿¡ããã
match.params.numberæ ŒçŽãã
match.params.number ã ããšãã°ãpath
/roster/6 ããã©ã¡ãŒã¿ãŒã䜿çšããŠæ¬¡ã®ãªããžã§ã¯ããçæããŸãã
{ number: '6'
<Player/>ã³ã³ããŒãã³ãã¯
props.match.paramsã䜿çšããŠãã¬ã³ããªã³ã°ããå¿
èŠãããæ
å ±ãååŸããŸãã
æ³šïŒ path-to-regexpã§
ãã¹ãªãã·ã§ã³ã®è©³çްã確èªã§ããŸãã
<Player/>ã³ã³ããŒãã³ãã«å ããŠãåœç€Ÿã®Webãµã€ãã§ã¯
<FullRoster/> ã
<Schedule/>ããã³
<Home/>ãŸãã
const FullRoster = () => ( <div> <ul> { PlayerAPI.all().map(p => ( <li key={p.number}> <Link to={`/roster/${p.number}`}>{p.name}</Link> </li> )) } </ul> </div> ) const Schedule = () => ( <div> <ul> <li>6/5 @ </li> <li>6/8 vs </li> <li>6/14 @ </li> </ul> </div> ) const Home = () => ( <div> <h1> !</h1> </div> )
åç
§è³æ
æåŸã«ãç§ãã¡ã®ãµã€ãã«ã¯ããŒãžéã®ããã²ãŒã·ã§ã³ãå¿
èŠã§ãã éåžžã®ãªã³ã¯ãäœæãããšãããŒãžããªããŒããããŸãã React Routerã¯ãåèµ·åãé²ã
<Link/>ã³ã³ããŒãã³ãã䜿çšããŠãã®åé¡ã解決ããŸãã
<Link/>ãã¯ãªãã¯ãããšãURLãæŽæ°ãããReact Routerã¯ããŒãžãæŽæ°ããã«ç®çã®ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããŸãã
import { Link } from 'react-router-dom' const Header = () => ( <header> <nav> <ul> <li><Link to='/'>Home</Link></li> <li><Link to='/roster'>Roster</Link></li> <li><Link to='/schedule'>Schedule</Link></li> </ul> </nav> </header> )
<Link/>ã¯prop
to䜿çš
toãŠãè¡ãå
ã®URLãèšè¿°ããŸãã Prop toã¯ãæååãŸãã¯å Žæãªããžã§ã¯ãïŒãã¹åãæ€çŽ¢ãããã·ã¥ãç¶æ
ã®ããããã£ã§æ§æãããïŒã«ããããšãã§ããŸãã ãããæååã®å Žåããã±ãŒã·ã§ã³ãªããžã§ã¯ãã«å€æãããŸãã
<Link to={{ pathname: '/roster/7' }}>Player #7</Link>
æ³šïŒ <Link/>ã³ã³ããŒãã³ãã®ãã¹ã¯çµ¶å¯Ÿãã¹ã§ãªããã°ãªããŸãã[4]ã
宿œäŸ
ãŠã§ããµã€ãã®ãã¹ãŠã®ã³ãŒãã¯ãcodepenã®
ãã®ã¢ãã¬ã¹ã§å
¥æã§ããŸãã
ã«ãŒãã®æºåãã§ããŸããïŒ
ããã§ãWebã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã£ã³ã°ã®è©³çްã«é£ã³èŸŒãæºåãã§ããããšãé¡ã£ãŠããŸãã
ç¬èªã®Webã¢ããªã±ãŒã·ã§ã³ïŒ
<BrowserRouter.>, <Route.>, and <Link.> ïŒãäœæãããšãã«å¿
èŠãšãªãæãåºæ¬çãªã³ã³ããŒãã³ãã䜿çšããŸããããããã§ã¯èª¬æãããŠããªãã³ã³ããŒãã³ããšãããããããã€ããããŸãã 幞ããªããšã«ãReact Routerã«ã¯åªãã
ããã¥ã¡ã³ãããããã³ã³ããŒãã³ããå°éå
·ã®ãã詳现ãªèª¬æãèŠã€ããããšãã§ããŸãã ããã¥ã¡ã³ãã«ã¯ããœãŒã¹ã³ãŒããå«ãå®çšçãªäŸãèšèŒãããŠããŸãã
説æ
[1]-ãã±ãŒã·ã§ã³ãªããžã§ã¯ãã¯ãURLã®ããŸããŸãªéšåãèšè¿°ããŸã
[2]-ãã¹ãªãã§
<Route/>ã³ã³ããŒãã³ãã䜿çšã§ããŸãã ããã¯ã
contextä¿åãããŠããã¡ãœãããšå€æ°ãæž¡ãã®ã«äŸ¿å©ã§ãã
[3]-propã®
childrenã䜿çšããå Žåãpathãšlocation.pathnameãäžèŽããªãå Žåã§ããã«ãŒããã¬ã³ããªã³ã°ãããŸãã
[4]-
<Route/>ããã³
<Link/>çžå¯Ÿãã¹ã§äœæ¥ãé²è¡äžã§ãã çžå¯Ÿ
<Link/>èŠãç®ãããè€éã§ããçŸåšã®URLã§ã¯ãªãã芪ã®
matchãªããžã§ã¯ãã䜿çšããŠè§£æ±ºããå¿
èŠããããŸãã
[5]-ããã¯ã¹ããŒãã¬ã¹ã³ã³ããŒãã³ãã§ãã å
éšã«ã¯
renderãš
componentéã«å€§ããªéãããã
component ã ã³ã³ããŒãã³ãã¯
React.createElementã䜿çšããŠã³ã³ããŒãã³ããäœæãã
render颿°ãšããŠäœ¿çšãããŸãã ã€ã³ã©ã€ã³é¢æ°ãå®çŸ©ããŠ
propsãæž¡ããšã
render颿°ã䜿çšãããããã¯ããã«é
ããªããŸãã
<Route path='/one' component={One}/>
[6]-ã³ã³ããŒãã³ã
<Route/> <Switch/>ã¯äž¡æ¹ãšãæ¯æ±ã®äœçœ®ã䜿çšã§ããŸãã ããã«ãããå®éã«çŸåšã®URLãšã¯ç°ãªããã¹ã«ãããããããšãã§ããŸãã
[7]
staticContextãéä¿¡ããŸããããµãŒããŒäžã§ã¬ã³ããªã³ã°ããå Žåã«ã®ã¿åœ¹ç«ã¡ãŸãã