تا به اینجای آموزش، برنامه ما فقط محدود به یک صفحه بود. اما کمتر پیش می آید که یک برنامه پیچیده تنها از یک صفحه یا ویو تشکیل شده باشد. برای نمونه، یک برنامه ممکن است شامل یک صفحه لاگین باشد تا کاربران از طریق این صفحه به سایت لاگین کنند، یا یک صفحه جستجو که کاربران در آن یک عبارت را جستجو کنند. اینها ویوهای مختلف با ساختارهای متفاوتی هستند. حال می خواهیم ببینیم چطور می شود این ساختار را در برنامه خود پیاده کنیم.
در این برنامه برای مدیریت لینک صفحات مختلف از کتابخانه react-router استفاده می کنیم. بنابراین قبل از استفاده از این کتابخانه، ابتدا باید آنرا با دستور زیر نصب کنیم:
npm install --save react-router-dom
بعد از نصب react-router چند پکیج را از داخل این کتابخانه وارد (import) برنامه کرده و ساختار برنامه را بروزرسانی می کنیم. اما قبل از اینکه بروزرسانی را انجام دهید، یک قدم به عقب برگردید. ببینید که چرا و چگونه ساختار برنامه خود را با این روش باید انجام دهیم.
در قسمت های قبلی دیدیم که چطور با استفاده از کامپوننت ها یک ساختار درختی ایجاد کردیم. با مطالبی که درباره برنامه تک صفحه ای با مسیردهی گفتیم، می توانیم به قسمت های مختلف یک صفحه به عنوان فرزندان یا زیرکامپوننت ها، نگاه کنیم.
با استفاده از مسیردهی در یک برنامه تک صفحه ای می توانیم بخشی از یک آدرس را گرفته و آن را با آدرس دیگری جایگزین کنیم. با این روش می توانیم به طور دینامیک در مرورگر بین آدرس های مختلف جابجا شویم.
به بیان دیگر، یک کامپوننت ری اکت را به عنوان کامپوننت ریشه (root) برای عناصر داخل برنامه تعریف می کنیم. سپس می توانیم به ری اکت بگوییم که با جایگزین کردن یک کامپوننت به جای دیگری، نمای ظاهری یک ویو را به طور کلی تغییر دهد.
کامپوننت App را باز کرده و تمام روت های مورد نیاز را در این کامپوننت تعریف می کنیم. همچنین باید تعدادی کامپوننت را از پکیج react-router گرفته و به برنامه وارد کنیم. این کامپوننت ها عبارتند از:
از این کامپوننت ها برای مسیردهی کامپوننت های پروژه استفاده می کنیم. بر اساس آدرس یا روتی که در مرورگر وارد می شود، کامپوننت مورد نظر که به عنوان فرزند <BrowserRouter/> قرار گرفته، نمایش داده می شود.
از کامپوننت <Router/> برای ساخت یک روت در یک مسیر مشخص که با یک URL آدرس دهی می شود، استفاده می کنیم.
یک روش دیگر برای مدیریت پیمایش در سمت کلاینت، استفاده از علامت # یا Hash در آدرس روت مورد نظر است. با این روش به مرورگر می گوییم که چطور پیمایش بین صفحات مختلف برنامه را مدیریت کند.
فایل src/App.js را برای وارد کردن این ماژول ها به برنامه، بروزرسانی می کنیم. کامپوننت BrowserRouter را به برنامه وارد کرده و با استفاده از سینتکس ES6 (اکما اسکریپت 6) یک اسم متفاوت برای آن انتخاب می کنیم:
import React from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom' export class App extends React.Component { render() { <Router> {/* routes will go here */} </Router> } }
حال با استفاده از کامپوننت <Router/> که در تابع ()render
قرار دادیم، روت های مسیردهی را تعریف می کنیم. در اینجا ما با استفاده از پروپرتی history نوع مسیردهی مان را تعریف می کنیم. در این مثال، ما از نوع history ی hash استفاده می کنیم.
export class App extends React.Component { // ... render() { <Router> {/* routes will go here */} </Router> } // ... }
حال می خواهیم اولین روت را تعریف کنیم. از کامپوننت <Route/> که از پکیج react-router وارد برنامه کردیم، برای تعریف یک روت استفاده و پروپرتی های زیر را به آن ارسال می کنیمم:
حال می خواهیم برای مسیر ریشه، یک روت به همراه یک کامپوننت stateless تعریف کنیم. این کامپوننت یک سری محتوای استاتیک را نمایش می دهد:
const Home = () => (<div><h1>Welcome home</h1></div>) // ... class App extends React.Component { render() { return ( <Router> <Route path="/" component={Home} /> </Router> ) } }
با وارد کردن آدرسی که در قسمت path مشخص شده، کامپوننت home رندر می شود. حال یک روت دیگر برای آدرس about/ یا درباره سایت، اضافه می کنیم:
const Home = () => (<div><h1>Welcome home</h1></div>) // ... class App extends React.Component { render() { return ( <Router> <div> <Route path="/" component={Home} /> <Route path="/about" component={About} /> </div> </Router> ) } }
همچنین باید یک لینک (تگ<a> </a>
) در صفحه قرار دهیم تا کاربران بتوانند توسط آن به روت هایی که تعریف کردیم، پیمایش کنند. اما با استفاده از این تگ مرورگرها با آن روت به عنوان یک روت سمت سرور رفتار می کنند. یعنی وقتی روی آن کلیک می کنیم صفحه رفرش شده و به لینک جدید منتقل می شود. پس برای جلوگیری از این امر باید از یک کامپوننت دیگری به نام <Link />
به جای تگ <a /> استفاده کنیم.
کامپوننت <Link />
نیاز به یک پروپرتی به نام to
دارد که این پروپرتی روت سمت کلاینتی که می خواهیم آنرا رندر کنیم، مشخص می کند.
حال کامپوننت های Home و About را بروزرسانی کرده و از <Link /> به جای <a /> استفاده می کنیم:
const Home = () => (<div><h1>Welcome home</h1><Link to='/about'>Go to about</Link></div>) const About = () => (<div><h1>About</h1><Link to='/'>Go home</Link></div>)
یک لحظه صبر کنید... ما نمی خواهیم که هر دو روت را با هم نمایش دهیم. اما با کدهای بالا، این اتفاق می افتد، چون react-router
تمام محتواهایی که با یک مسیر (Path) مطابقت پیدا کنند را رندر می کند.
در این مورد، باید از کامپوننت switch
استفاده کنیم.
چون react-router سعی در رندر کردن هر دو کامپوننت دارد، ما باید مشخص کنیم که تنها می خواهیم یک مطابقت دقیق (exact) روی کامپوننت ریشه داشته باشیم:
const Home = () => (<div><h1>Welcome home</h1><Link to='/about'>Go to about</Link></div>) // ... class App extends React.Component { render() { return ( <Router> <Switch> <Route path="/about" component={About} /> <Route path="/" component={Home} /> </Switch> </Router> ) } }
اگر چه در این مقاله نمی توانیم به طور مفصل به react-router بپردازیم، اما بهتر است روش های مختلفی که می توانیم یک زیرکامپوننت را برای رندر دریافت کنیم، یاد بگیریم.
ما قبلاً ساده ترین روش ممکن، یعنی استفاده از پروپرتی component را یاد گرفتیم، اما یک روش قدرتمند دیگر، استفاده از پروپرتی render
است. پروپرتی render یک تابع را گرفته و با آبجکت مطابقت داده شده به همراه مکان و پیکربندی روت مورد نظر فراخوانی می شود.
پروپرتی render به ما اجازه می دهد تا هر چه را که بخواهیم در یک مسیر فرزند (subroute) رندر کنیم، که این شامل رندر روت های دیگر هم می شود.
در مثال زیر به طور عملی، با این موضوع آشنا می شوید:
const Home = () => (<div><h1>Welcome home</h1><Link to='/about'>Go to about</Link></div>) const About = ({ name }) => (<div><h1>About {name}</h1></div>) // ... class App extends React.Component { render() { return ( <Router> <Switch> <Route path="/about" render={(renderProps) => ( <div> <Link to='/about/ari'>Ari</Link> <Link to='/about/nate'>Nate</Link> <Route path="/about/:name" render={(renderProps) => ( <div> <About name={renderProps.match.params.name} /> <Link to='/'>Go home</Link> </div> )} /> </div> )} /> <Route path="/" render={(renderProps) => ( <div> Home is underneath me <Home {...this.props} {...renderProps} /> </div> )} /> </Switch> </Router> ) } }
حال ما چندین صفحه در برنامه مان داریم. همچنین دیدیم که چطور می توان در این روت ها، یک زیر کامپوننت را رندر کنیم.
React-router قابلیت های زیادی دارد که در این مقاله نمی توانیم به تمام آنها بپردازیم. برای کسب اطلاعات بیشتر به آدرس های زیر مراجعه کنید.
در درس بعدی، کار با Redux را شروع کردیم، در آن درس روش های پیچیده مدیریت داده را بررسی خواهیم کرد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.