حالا که با مبحث Route های تو در تو آشنا شدیم باید به سراغ Redirect کردن یا انتقال کاربر از صفحه ای به صفحه ی دیگر برویم. کد فعلی ما برای Route ها بدین شکل است:
<Switch> <Route path="/new-post" component={NewPost} /> <Route path="/posts" component={Posts} /> </Switch>
حالا فرض کنید بخواهیم کدها را طوری بنویسیم که اگر کاربر به جای posts/
به آدرس /
رفت، باز هم کامپوننت posts برایش نمایش داده شود. می توانیم به راحتی بگوییم:
<Switch> <Route path="/new-post" component={NewPost} /> <Route path="/posts" component={Posts} /> <Route path="/" component={Posts} /> </Switch>
حالا اگر به مرورگر بروید و آدرس http://localhost:3000/ را باز کنید باز هم کامپوننت posts برایتان به نمایش در می آید بنابراین به هدفمان رسیده ایم اما این کار redirect کردن نیست به همین دلیل آن را کامنت می کنم. برای redirect کردن واقعی کاربران به یک کامپوننت واقعی به نام Redirect نیاز داریم بنابراین دستور import زیر را در فایل Blog.js تغییر داده و Redirect را هم وارد پروژه می کنیم:
import { Route, NavLink, Switch, Redirect } from 'react-router-dom';
در قدم بعد باید به شکل زیر از آن استفاده کنیم:
<Switch> <Route path="/new-post" component={NewPost} /> <Route path="/posts" component={Posts} /> <Redirect from="/" to="/posts" /> {/* <Route path="/" component={Posts} /> */} </Switch>
From
یعنی «از» و to
یعنی «به»، به عبارت ساده تر این کامپوننت می گوید کاربر را از کدام صفحه به کدام صفحه منتقل کنم؟ در کد بالا به سادگی گفته ایم از /
به posts/
منتقل کن.
نکته: اگر کامپوننت Redirect را خارج از دستور استفاده کنید، دیگر اجازه ندارید from را مشخص کنید. یکی از این حالت ها Redirect کردن شرطی کاربران است که می خواهیم در مورد آن صحبت کنیم.
Redirect کردن کاربران به همین سادگی انجام می شود اما نوع دیگری از redirect کردن را نیز داریم که به آن conditional redirect (به معنی «redirect کردن شرطی») می گویند. برای تست آن وارد فایل NewPost.js شوید. فرض کنید می خواهیم با تکمیل شدن درخواست HTTP و کلیک روی دکمه ی submit کاربر را به صفحه ی دیگری منتقل کنیم. ابتدا باید کامپوننت Redirect را درون NewPost.js وارد کنیم:
import { Redirect } from 'react-router-dom';
حالا آن را در قسمت JSX و به شکل زیر می نویسیم:
return ( <div className="NewPost"> <Redirect to="/posts" /> <h1>Add a Post</h1> <label>Title</label> <input type="text" value={this.state.title} onChange={(event) => this.setState({ title: event.target.value })} /> <label>Content</label> <textarea rows="4" value={this.state.content} onChange={(event) => this.setState({ content: event.target.value })} /> <label>Author</label> <select value={this.state.author} onChange={(event) => this.setState({ author: event.target.value })}> <option value="Max">Max</option> <option value="Manu">Manu</option> </select> <button onClick={this.postDataHandler}>Add Post</button> </div> );
مشکلی که کد بالا دارد احتمالا برایتان واضح است. کد را ذخیره کنید و به مرورگر بروید. اگر روی لینک New Post کلیک کنید، سریعا به posts/ منتقل می شوید و حتی کامپوننت NewPost را نخواهید دید! از آنجایی که </ Redirect>
تنها یک کامپوننت عادی است می توانیم مانند بقیه ی کامپوننت ها با استفاده از یک شرط ساده آن را به صورت مشروط اضافه کنیم. برای انجام این کار ابتدا یک state جدید به state های قبلی اضافه می کنیم:
state = { title: '', content: '', author: 'Max', submitted: false }
مقدار submitted را در حالت عادی روی false گذاشته ایم تا فقط در صورتی که درخواست HTTP تکمیل شد آن را به true تبدیل کنیم. بنابراین در قسمت then از دستور Axios می گوییم:
postDataHandler = () => { const data = { title: this.state.title, body: this.state.content, author: this.state.author }; axios.post('/posts', data) .then(response => { console.log(response); this.setState({ submitted: true }); }); }
حالا می توانیم با استفاده از submitted کامپوننت Redirect را فعال یا غیرفعال کنیم. من به روش زیر عمل می کنم:
render() { let redirect = null; if (this.state.submitted) { redirect = <Redirect to="/posts" />; } return ( <div className="NewPost"> {redirect} <h1>Add a Post</h1> <label>Title</label> <input type="text" value={this.state.title} onChange={(event) => this.setState({ title: event.target.value })} /> <label>Content</label> <textarea rows="4" value={this.state.content} onChange={(event) => this.setState({ content: event.target.value })} /> <label>Author</label> <select value={this.state.author} onChange={(event) => this.setState({ author: event.target.value })}> <option value="Max">Max</option> <option value="Manu">Manu</option> </select> <button onClick={this.postDataHandler}>Add Post</button> </div> ); }
توضیح کد بالا:
این روش، روش بی نقص و جالبی برای redirect کردن کاربران است اما برخی اوقات نیاز به انجام این کار ها نداریم. در اکثر اوقات بعد از ثبت شدن یک فرم فقط می خواهیم صفحه را تغییر دهیم و شاید به صفحه ی دیگری برویم. اگر یادتان باشد شیء ای به نام history توسط router به ما پاس داده می شد و دارای متد هایی بود که با استفاده از آن ها می توانیم صفحه را تغییر دهیم.
به قسمت then از axios (در فایل NewPost.js) بروید و کد تغییر state را کامنت کنید تا هیچ گاه <Redirect> را در صفحه قرار ندهیم. سپس از متد push در شیء history استفاده کنید:
postDataHandler = () => { const data = { title: this.state.title, body: this.state.content, author: this.state.author }; axios.post('/posts', data) .then(response => { console.log(response); this.props.history.push('/posts') // this.setState({ submitted: true }); }); }
در واقع متد push به ما اجازه می دهد که یک صفحه ی جدید را push کنیم یا به زبان ساده تر کاربر را به صفحه ی جدیدی منتقل کنیم. اضافه کردن این یک خط کد، کار تمام کدهای قبلی را انجام می دهد. اگر به مرورگر مراجعه کنید کدهای ما دقیقا مثل قبل کار می کند و هیچ مشکلی در این زمینه نداریم (با اینکه با کامنت کردن setState برای submitted دیگر هیچ گاه <Redirect> را فعال نکرده ایم).
تفاوت جالبی که در استفاده از این دو دستور وجود دارد مسئله ی برگشت به صفحه ی قبلی است. اگر از دستور push استفاده کنید، می توانید با کلیک روی دکمه ی back مرورگر به صفحه ی قبلی برگردید اما اگر از <Redirect> استفاده کنید با کلیک روی back به صفحه ی قبلی منتقل نخواهید شد چرا که push کاربر را به صفحه ی جدید می برد اما <Redirect> صفحه ی فعلی را با صفحه ای جدید replace (جایگزین) می کند. اگر دوست ندارید از <Redirect> استفاده کنید و در عین حال می خواهید قابلیت برگشت به صفحه ی قبل را نیز نداشته باشیم می توانید به جای push از replace استفاده کنید:
axios.post('/posts', data) .then(response => { console.log(response); this.props.history.replace('/posts') // this.setState({ submitted: true }); });
من هر دو روش را به شما نشان دادم و جزئیات هر دو روش را نیز به شما گوشزد کردم. استفاده و انتخاب روش مناسب بر عهده ی شما و به اقتضای پروژه ی شما خواهد بود و هیچ روش درست یا غلط مطلقی وجود ندارد. امیدوارم درک نسبتا خوبی نسبت به فرآیند Redirect کردن کاربران پیدا کرده باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.