یکی از متداولترین مسئولیتهای توسعهدهندگان فرانتاند، مدیریت دادهها در برنامههای فرانتاندشان است. باید بتوانیم دادهها را از یک API بازیابی کنیم، بر روی آنها تغییراتی ایجاد نماییم و سپس در یک برنامه وب مدرن برای تعامل با کاربر، روی صفحه نمایش دهیم.
وجود یک ارتباط کارآمد بین قسمت فرانتاند و بکاند برای ایجاد برنامههای یکپارچه و ریسپانسیو بسیار مهم است.
اکنون سناریویی را تصور میکنیم که در آن با یک توسعهدهنده بکاند بر روی یک پروژه کار میکنیم و منتظر API endpoint هستیم تا به فرانتاند خود متصل شویم. یک ابزار عالی وجود دارد که توسعهدهندگان فرانتاند میتوانند از آن برای ایجاد یک API ساختگی در مرحله توسعه استفاده کنند. این ابزار JSON Server نام دارد.
در این مقاله قصد داریم تا نحوه استفاده از JSON serverها برای ذخیرهسازی داده در برنامههای React را بررسی کنیم. همچنین با پیادهسازی یک پروژه فرانتاند، با ویژگیها و مزایای آن بیشتر آشنا خواهیم شد.
برنامهای که قصد داریم آن را پیادهسازی کنیم به کاربران این امکان را میدهد تا لیستی از کاربران و جزئیات اطلاعات آنها را مشاهده کنند. دادههای کاربر با استفاده از JSON server در یک فایل JSON در برنامه فرانتاند ایجاد میشود.
JSON مخفف عبارت JavaScript Object Notation است و یک ابزار Node.js سبک و با کاربری آسان میباشد که یک API RESTful را با استفاده از یک فایل JSON به عنوان data source شبیهسازی میکند. توسعهدهندگان فرانتاند با کمک JSON Server میتوانند APIهای ساختگی را بدون نیاز به نوشتن کدهای پیچیده سمت سرور یا زمانی که API پشتیبان هنوز آماده نیست ایجاد کنند.
این API ساختگی درخواستها را به endpointای که ارائه خواهد شد ارسال میکند، به درخواستهای HTTP پاسخ میدهد و به این ترتیب کار را برای توسعه سریع برای توسعهدهندگان فرانتاند ایدهآل میکند. JSON Server همچنین توسعهدهندگان را قادر میسازد تا عملیات CRUD را انجام دهند و دادهها را در فایلهای JSON ذخیره کنند. فایل JSON به عنوان مقادیر key-value و در قالب زیر نوشته میشود:
{ "name": "Jane", "age": 30, "gender": "Female" }
به name
، age
و gender
keyگفته میشود و Jane
، ۳۰
و female
value هر یک از این keyها هستند.
فایل داده JSON میتواند در دو فرمت آرایه و آبجکت با آیجکتهای تودرتو ارائه شود.
فرمت آرایه
[ { "id": 1, "name": "John Doe", "age": 25 }, { "id": 2, "name": "Jane Smith", "age": 40 } ]
فرمت آبجکت با آبجکتهای تودرتو
{ "users": { "۱": { "name": "John Doe", "age": 25 }, "۲": { "name": "Jane Smith", "age": 30 } } }
در ادامه برخی از ویژگیهای JSON Server را داریم که عبارتند از:
GET
، POST
، PUT
و DELETE
پشتیبانی میکند.Create
، Read
، Update
و Delete
(CRUD) را روی دادهها انجام دهیم تا بتوانیم یک برنامه تعاملی بسازیم.در این بخش به برخی از مزایای استفاده از JSON Server اشاره میکنیم که عبارتند از:
ما باید Node.js و npm را روی سیستم خود نصب کنیم، زیرا هر دو پیش نیاز این تنظیمات هستند. سپس مراحل زیر را برای راهاندازی و استفاده از JSON Server در برنامه فرانتاند خود دنبال میکنیم:
برای نصب JSON Server در برنامه خود، به دایرکتوری پروژه خود در ترمینال یا خط فرمان میرویم و دستور زیر را تایپ میکنید:
npm install -g json-server
با این کار JSON Server به صورت سراسری روی سیستم ما نصب میشود. اگر بخواهیم آن را به صورت محلی فقط برای یک پروژه خاص نصب کنیم، از دستور زیر استفاده میکنیم:
npm i json-server
یک فایل JSON در دایرکتوری پروژه خود ایجاد میکنید که به عنوان data source عمل میکند. این فایل JSON باید پسوند فایل json.
داشته باشد. یعنی اگر بخواهیم نام فایل JSON ما db
باشد، فایلی به نام db.json
ایجاد میکنیم.
دادههای خود را در فایل JSON تعریف میکنیم. این دادههای JSON میتوانند آرایهای از آبجکتها یا یک آبجکت با آبجکتها تودرتو باشند. هر آبجکت یک موجودیت داده را نشان میدهد که باید یک id
منحصربهفرد داشته باشد.
JSON Server را با تایپ این دستور در ترمینال خود راهاندازی میکنید: json-server --watch db.json
. به طور پیشفرض روی آدرس https://localhost:3000
اجرا میشود. هنگام راهاندازی سرور با استفاده از flag --port
، میتوانیم پورتی را که روی آن اجرا میشود، با تعیین شماره پورت دیگری تغییر دهیم.
به عنوان مثال، اگر بخواهیم سرور ما به جای پورت پیشفرض (۳۰۰۰) روی پورت ۸۰۰۰ اجرا شود، هنگام راهاندازی سرور باید از این دستور استفاده کنیم: json-server --watch db.json --port 8000
. سپس میتوانیم آن را در مرورگر خود روی پورت ۸۰۰۰ مشاهده نماییم.
JSON Server به طور خودکار endpointهای RESTful را بر اساس دادههایی که در فایل JSON خود تعریف کردهایم، ایجاد میکند.
اگر یک فایل JSON با آرایهای از users
داریم، این endpoint است که به طور خودکار توسط JSON Server ایجاد میشود:
GET /users
– فهرستی از تمام موجودیتهای منابع کاربران را بازیابی میکند.GET /users/:id
– یک کاربر خاص را با id
خود بازیابی میکند.POST /users
– یک کاربر جدید ایجاد میکند.PUT /users/:id
– یک کاربر را بر اساس id
مشخص شده بهروزرسانی میکند.DELETE /users/:id
– یک کاربر را بر اساس id
مشخص شده حذف میکند.این الگو تعامل با API ساختگی را به روش RESTful و درست مانند API واقعی بکاند انجام میدهد.
برای درک بیشتر نحوه استفاده از JSON Server در یک پروژه واقعی، یک مثال را باهم بررسی میکنیم. ما یک برنامه ساده React.js خواهیم ساخت که دادههای کاربران را از یک فایل داده JSON با استفاده از JSON Server در قسمت فرانتاند نمایش میدهد.
این برنامه فقط دو صفحه خواهد داشت. صفحه اول لیستی از کاربران همراه با نام و آدرس ایمیل آنها را دربرمیگیرد. با کلیک روی دکمه مشاهده جزئیات کامل، وارد صفحه دیگری میشویم که جزئیات بیشتر در مورد هر کاربر را بر اساس id
کاربری آن، نمایش میدهد.
با استفاده Vite یک برنامه React ایجاد میکنیم. برای انجام این کار دستور زیر را اجرا مینماییم:
yarn create vite
نام پروژه را انتخاب کرده و React را به عنوان فریمورک و تایپ اسکریپت را به عنوان variant انتخاب میکنیم. در صورت تمایل میتوانیم از جاوااسکریپت هم به عنوان variant استفاده کنیم.
پس از انجام این کار، به پروژه خود میرویم و با کمک دستور yarn
نصب dependencyها را انجام میدهیم. پس از اینکه dependencyها را با موفقیت نصب کردیم، سرور توسعه خود را با این دستور اجرا میکنیم: yarn run dev
. مرورگر خود را باز کرده و URL (http://127.0.0.1:5173/
) را جایگذاری مینماییم و به این ترتیب، برنامه در حال اجرا خود را در مرورگر مشاهده میکنیم.
با استفاده از دستور زیر JSON server را در برنامه خود نصب میکنید:
برای نصب سراسری: npm install -g json-server
برای نصب محلی: npm i json-server
آخرین پکیجی که نصب میکنیم react-router است تا با استفاده از آن، از page navigation بهرهمند شویم: npm i react-router-dom
.
اکنون میخواهیم برنامهای که داریم ساختار پوشهای مرتب داشته باشد، بنابراین این دستورالعملها را دنبال میکنیم:
ابتدا یک پوشه data
در دایرکتوری root پروژه خود میسازیم. در داخل این پوشه data
، یک فایل JSON به نام db.json
ایجاد میکنیم. این فایل جایی است که دادههای JSON تعریف میشوند.
سپس، در دایرکتوری src، یک پوشه components
ایجاد میکنیم. در این پوشه ۳ فایل Home.tsx
، UserDetails.tsx
و UserList.tsx
را میسازیم. اینها کامپوننتهایی هستند که منطق و رابط کاربری برنامه را رندر میکنند.
در دایرکتوری src یک فایل با نام useFetch.tsx
ایجاد میکنیم. این فایل حاوی کد اجرای API خواهد بود. کامپوننت اصلی برنامه ما، یعنی فایل App.tsx
جایی است که ما مسیریابی صفحات را در آن مدیریت خواهیم کرد.
اولین کامپوننتی که باید تغییراتی را در آن ایجاد کنیم فایل App.tsx
است. خطوط کد زیر را در کامپوننت قرار میدهیم:
import Home from './components/Home'; import UserDetails from './components/UserDetails'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/users/:id" element={<UserDetails />} /> </Routes> </Router> ) } export default App
این فایل فقط برای رندر مسیرهایی برای برنامه است.
به فایل db.json
میرویم و دادههای JSON خود را در داخل آن تعریف میکنیم:
{ "users": [ { "id": 1, "name": "Juliet Oma", "email": "julie@yahoo.com", "number": "08100000000" }, { "id": 2, "name": "James Williams", "email": "jameswilly@gmail.com", "number": "08111111111" }, { "id": 3, "name": "Ahmed Ali", "email": "ahmedali012@gmail.com", "number": "09022222222" }, { "id": 4, "name": "Grace Funsho", "email": "gracefunsho@gmail.com", "number": "09033333333" } ] }
server خود را با استفاده از دستور زیر راهاندازی میکنیم:
json-server --watch db.json --port 8000
این دستور فایل db.json
را مشاهده میکند و API endpointای را که روی پورت ۸۰۰۰ اجرا میشود، درون آن قرار میدهد.
اگر URL (http://localhost:8000/users
) ارائه شده در ترمینال را کپی کنیم و آن را در مرورگر خود باز نماییم، یک داده JSON خواهیم دید که تمام دادههای کاربری را که در فایل db.json
خود تعریف کردهایم به نمایش میگذارد.
در مرحله بعد، باید برای پیادهسازی API کدنویسی انجام دهیم. این کار را در فایل useFetch.tsx
انجام خواهیم داد. این فایل اساساً یک هوک سفارشی React است که برای مدیریت دریافت دادههای asynchronous از یک URL مشخص، ایجاد میکنیم.
import { useState, useEffect } from 'react'; interface UseFetchResult { data: any | null; isPending: boolean; error: any | null; } const useFetch = (url: string): UseFetchResult => { const [data, setData] = useState<any | null>(null); const [isPending, setIsPending] = useState<boolean>(true); const [error, setError] = useState<any | null>(null); useEffect(() => { setTimeout(() => { fetch(url) .then(res => { if (!res.ok) { throw Error('Error fetching users data'); } return res.json(); }) .then(data => { setData(data); setIsPending(false); setError(null); }) .catch(err => { setIsPending(false); setError(err.message); }); }, ۱۰۰۰); }, [url]); return { data, isPending, error }; } export default useFetch;
ابتدا هوکهای useState
و useEffect را import میکنیم تا از آنها برای مدیریت stateها و انجام side effectها در هوک سفارشی استفاده کنیم.
هنگام تنظیم پروژه، تایپ اسکریپت را به عنوان یک variant انتخاب کردیم. بنابراین، باید یک interface به نام useFetchResult
تعریف کنیم تا ساختار آبجکت نتیجهای را که هوک useFetch
return میکند را مشخص نماید. این interface شامل سه ویژگی است: data
، isPending
و error
.
کد const useFetch = (url: string): UseFetchResult => { ... }
هوک سفارشی useFetch
را تعریف میکند. یک پارامتر url
از نوع رشته میگیرد و یک آبجکت برمیگرداند که با اینترفیس UseFetchResult
مطابقت دارد.
در مرحله بعد، باید با استفاده از هوک useState
سه متغیر را مقداردهی اولیه کنیم: data
برای ذخیره دادههای دریافت شده، isPending
برای نشان دادن اینکه آیا دریافت داده در حال انجام است یا خیر و state error
برای ذخیره هر گونه خطایی که در طول فرآیند دریافت رخ میدهد. هر کدام به ترتیب دارای مقدار اولیه null
، true
و null
هستند.
هوک useEffect
برای دریافت دادهها هنگام تغییر URL استفاده میشود. این هوک پس از رندر اولیه و هر زمان که وابستگی URL تغییر کند، اجرا میشود. در داخل تابع useEffect
، یک setTimeOut
برای شبیهسازی یک تاخیر ۱۰۰۰ میلی ثانیهای (۱ ثانیه) قبل از شروع دریافت دادهها تعریف شده است.
از متد fetch
برای درخواست GET
به URl مشخص شده استفاده میشود. responseای که برمیگردد با استفاده از res.ok
بررسی میشود. اگر ok نباشد، خطا رخ میدهد. سپس response با استفاده از متد res.json()
به JSON تبدیل شده و در متغیر data
ذخیره میشود. state isPending
روی false
تنظیم میشود تا نشان دهد دریافت دادهها کامل شده است و state error
روی null
تنظیم میشود تا خطای قبلی پاک شود.
اگر در طول فرآیند دریافت دادهها خطایی رخ دهد، در بلاک .catch
ثبت میشود. isPending
روی false
تنظیم میشود و سپس state error
با پیام خطا بهروزرسانی میگردد.
هوک سفارشی یک آبجکت حاوی data
، isPending
و stateهای error
را return میکند و به کامپوننتهای دیگر اجازه میدهد تا به داده دریافت شده و state آن دسترسی داشته باشند.
UserList.tsx
کامپوننتی است که تمام اطلاعات کاربر را در یک جدول نمایش میدهد. در فایل UserList.tsx
خود، کد زیرا را مینویسیم:
import React from 'react'; import { Link } from 'react-router-dom'; interface User { id: number; name: string; email: string; number: string; } interface UserListProps { users: User[]; name: string; } const UserList: React.FC<UserListProps> = ({ users, name }) => { return ( <> <section> <section> <h1>Users List</h1> </section> <section> <table> <thead> <tr> <th>Name</th> <th>Email</th> <th>Details</th> </tr> </thead> <tbody> {users.map((user) => ( <tr key={user.id}> <td> <p>{user.name}</p> </td> <td> <p>{user.email}</p> </td> <td> <Link to={`/users/${user.id}`}> <button> View full details </button> </Link> </td> </tr> ))} </tbody> </table> </section> </section> </> ); }; export default UserList;
کار خود را با import کردن Link
از کتابخانه react-router-dom
شروع میکنیم.
خط بعدی کد interface User
است، یک interface تایپ اسکریپ که ساختار یک آبجکت کاربر را تعریف میکند که دارای چهار ویژگی است و هر ویژگی دارای یک نوع داده مشخص میباشد.
سپس interface UserListProps
را داریم که ساختار یک آبجکت را تعریف میکند که دارای دو ویژگی user
و name
است. users
آرایهای از آبجکتها است که با interface User
مطابقت دارد.
این کامپوننت یک آبجکت با interface userListProps
را به عنوان آرگومان میگیرد، users
را از آن destruct کرده و به عنوان props در کامپوننت استفاده میکند.
پس از آن، المنت JSX را برای نمایش لیست کاربران در قالب جدول داریم. ما با استفاده از متد map
بر روی users
هر کاربر را در یک ردیف رندر میکنیم.
سپس یک دکمه به هر ردیف اضافه میکنیم که عمل navigation را به یک مسیر خاص (/users/${user.id}
) انجام میدهد. این مسیرها اطلاعات دقیق کاربری را که id
او به عنوان بخشی از URL ارائه شده است، نمایش میدهد.
ما از یک قالب literal برای ایجاد یک URL داینامیک که شامل مقدار user.id
است استفاده کردیم.
کامپوننت بعدی که روی آن کار خواهیم کرد، کامپوننت Home.tsx
است. این همان جایی است که لیست کاربران بر روی صفحه، نمایش داده میشود و صفحه اصلی برنامه ما به حساب میآید.
import UserList from './UserList'; import useFetch from '../useFetch'; const Home = (): JSX.Element => { const { data: users, isPending, error } = useFetch('http://localhost:8000/users') return ( <section> {error && <p>{error}</p>} {isPending && <p>Loading users...</p>} {users && <UserList users={users} />} </section> ); }; export default Home;
ابتدا کامپوننت UserList
و هوک سفارشی useFetch
را از جایی که در دایرکتوری پروژه قرار دارند import میکنیم.
خط کد const { data: users, isPending, error } = useFetch('http://localhost:8000/users')
هوک سفارشی useFetch
را برای دریافت دادهها از URL مشخص شده فراخوانی میکند (http://localhost:8000/users
). هوک یک آبجکت با سه ویژگی return میکند: data
(کاربران دریافت شده)، isPending
(وضعیت لود) و error
(پیام خطا).
ما رابط کاربری را با المنتهای JSX رندر کردیم. اگر state error
دارای یک مقدار باشد، یک المنت پاراگراف حاوی پیام خطا را رندر میکند. اگر state isPending
مقدار true
داشته باشد، یک المنت پاراگراف را نمایش میدهد که نشان میدهد users
در حال بارگیری است. درنهایت اگر state users
دادهای داشته باشد (یعنی null
نباشد)، کامپوننت UserList
را رندر میکند و دادههای کاربران را به عنوان prop ارسال مینماید.
ما میخواهیم یک functionality اضافی به برنامه خود بیافزاییم که در آن میتوانید بر روی دکمه مشاهده جزئیات کامل که در همان ردیف با نام کاربر قرار دارد کلیک کنیم و جزئیات بیشتری را در مورد آن کاربر خاص در صفحه دیگری مشاهده نماییم. در کامپوننت Userdetails.tsx
کد زیر را داریم:
import { useParams } from 'react-router-dom'; import useFetch from '../useFetch'; const UserDetails = () => { const { id } = useParams(); const { data: user, error, isPending } = useFetch("http://localhost:8000/users/" + id); return ( <> <section> {isPending && <p>Loading user details...</p>} {error && <p>{error}</p>} {user && ( <> <h1>User {user.id} details</h1> <h2>{user.name}</h2> <p>{user.email}</p> <p>{user.number}</p> </> )} </section> </> ); }; export default UserDetails;
هوک useParams
را از کتابخانه react-router-dom
import میکنیم. این هوک امکان دسترسی به پارامترهای URL را برای ما فراهم میکند. همچنین هوک سفارشی useFetch
را هم import میکنیم.
const { id } = useParams();
از هوک useParams
برای استخراج پارامتر id
از URL استفاده میکند. این کد معمولاً در مسیرهایی مانند /users/:id
مورد استفاده قرار میگیرد.
در خط بعدی، هوک سفارشی useFetch
را برای دریافت دادهها از URL یک کاربر خاص بر اساس پارامتر id
استخراج شده، فراخوانی میکند. هوک یک آبجکت با ویژگی های data
، error
و isPending
را return میکند.
سپس المنتهای JSX میآیند تا جزئیات کاربران را رندر کنند. {isPending && <p>Loading user details...</p>}
یک پاراگراف رندر میکند که نشان میدهد در صورتی که isPending
مقدار true
داشته باشد، جزئیات کاربر بارگیری میشود.
اگر خطایی وجود داشته باشد، {error && <p>{error}</p>}
یک پاراگراف را نمایش میدهد که پیام خطا را در آن به نمایش میگذارد. در حالی که {user && (...)}
برخی از جزئیات کاربر مانند id
، name
، email
و number
را در صورت موجود بودن دادهها رندر میکند.
هنگامی که به مرورگر خود بازگردیم، لیستی از دادههای کاربر را در یک جدول مشاهده خواهیم کرد. هر ردیف کاربر در جدول دارای دکمهای است که میتوانیم روی آن کلیک کنیم تا صفحهای برای ما باز شود و جزئیات کامل آن کاربر خاص را ببینیم.
پس از استایلدهی برنامه، یک دمو از آن را در این لینک داریم.
همینطور میتوانیم دادههای کاربر را تغییر دهیم یا جزئیات بیشتری مانند توضیحات شغل کاربران، عنوان آنها و غیره را در فایل db.json
خود به لیست کاربران خود اضافه کنیم و تغییرات را در فهرست مرورگر مشاهده نماییم.
در این مقاله سعی کردیم تا با JSON server و نحوه استفاده از آن در یک برنامه React.js فرانتاند آشنا شویم.
همچنین میتوانیم عملیات CRUD کامل را با این دادهها از فایل JSON خود در قسمت فرانتاند برنامهای که داریم انجام دهیم. ما در این مقاله فقط عملیات Read را بررسی کردیم.
همینطور مثالی که باهم بررسی کردیم، درخواستی را به API endpoint ارائه شده هنگام راهاندازی JSON server ارسال میکند و پاسخ را در مرورگر نمایش میدهد. این اساساً نحوه عملکرد یک API server بکاند واقعی است. در این مثال، ما توانستیم با استفاده از JSON server به فانکشنالیتی مورد نظر خود دست پیدا کنیم.
مهم است بدانیم که این API ساختگی JSON را نمیتوانیم در مرحله تولید مورد استفاده قرار دهیم. فقط در مرحله توسعه برای ایجاد دادههای ساختگی JSON قابل استفاده میباشد. این بدان معناست که ما نمیتوانیم آن را به پروژه نهایی ارسال کنیم زیرا فایل داده JSON فقط بر روی یک پورت localhost اجرا میشود.
۵۰ درصد تخفیف ویژه پاییز فرانت کست تا پایان هفته
کد تخفیف: atm
دیدگاهها: