Next.js Client-Side Rendering (CSR) & SWR Data Fetching Sinhala Guide | Developer Tips
Next.js වල Client-Side Data Fetching (CSR) & SWR සමග පහසුවෙන් දත්ත ලබාගනිමු | Sinhala Guide
ආයුබෝවන් යාළුවනේ! අද අපි Next.js වල තවත් වැදගත් පැතිකඩක් ගැන කතා කරන්නයි යන්නේ. Next.js කිව්වම අපිට මුලින්ම මතක් වෙන්නේ Server-Side Rendering (SSR) සහ Static Site Generation (SSG) වගේ දේවල්නේ. ඒ වුණාට හැම තිස්සෙම ඒ දෙකම අවශ්ය වෙන්නේ නැහැ. සමහර වෙලාවට අපිට Client-Side Rendering (CSR) වගේම Client-Side Data Fetching කරන්නත් සිද්ධ වෙනවා.
ඉතින්, මේ ලිපියෙන් අපි බලමු:
- Next.js වල Client-Side Rendering (CSR) කියන්නේ මොකක්ද කියලා.
- සරලව Client-Side එකේ දත්ත ලබාගන්නේ කොහොමද කියලා.
- සාමාන්ය Client-Side Data Fetching වලට මුහුණ දෙන ගැටලු මොනවද කියලා.
- ඒ ගැටලු විසඳගන්න SWR වගේ library එකක් කොච්චර ප්රයෝජනවත්ද කියලා.
- කවදාද Client-Side Data Fetching එකක් තෝරාගත යුත්තේ කියලා.
ඔබ Next.js වලින් Application එකක් හදන කෙනෙක් නම් මේක ඔබට ගොඩක් වැදගත් වෙයි.
Next.js වල Client-Side Rendering (CSR) කියන්නේ මොකක්ද?
සරලවම කිව්වොත්, Client-Side Rendering (CSR) කියන්නේ වෙබ් පිටුවක් හෝ එහි කොටසක් browser එකේ JavaScript භාවිතයෙන් generate කිරීම. Next.js වලදී, අපි getStaticProps
හෝ getServerSideProps
වගේ data fetching functions භාවිතා නොකරන විට, Next.js විසින් page එකේ HTML එක generate කරනවා. නමුත් ඒ page එකට අවශ්ය දත්ත, user ගේ browser එකට load වුණාට පස්සේ, JavaScript code එක මගින් fetch කරලා, UI එකට render කරනවා.
මේක සාමාන්ය React Application එකක දත්ත fetch කරන විදියටම සමානයි. ඒ කියන්නේ, page එක මුලින්ම load වෙනකොට දත්ත නැහැ. දත්ත එන්නේ JavaScript මගින් API call එකක් ගහලා ඒකෙන් ලැබෙන response එක අනුව UI එක update කරන විටයි.
සාම්ප්රදායික Client-Side Data Fetching (useEffect
සහ fetch
)
මුලින්ම අපි බලමු සාමාන්ය විදියට useEffect
Hook එකයි, built-in fetch
API එකයි පාවිච්චි කරලා දත්ත ලබාගන්නේ කොහොමද කියලා. මේක තමයි React Developer කෙනෙක් විදියට මුලින්ම දත්ත ලබාගන්න ඉගෙන ගන්න ක්රමය.
උදාහරණයක් විදියට අපි Blog Posts ලැයිස්තුවක් API එකකින් ලබාගන්න හදනවා කියලා හිතමු.
import React, { useState, useEffect } from 'react';
function PostsList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setPosts(data);
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
};
fetchPosts();
}, []); // හිස් Dependency Array එකෙන් කියන්නේ මේක component එක mount වෙනකොට එක පාරක් විතරක් run වෙන්න ඕනේ කියලා.
if (loading) return <p>Posts loading... ⏳</p>;
if (error) return <p>Error loading posts: {error.message} ❌</p>;
return (
<div>
<h1>Blog Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default PostsList;
මේ Code එක හොඳට වැඩ කරනවා. නමුත් මේ ක්රමයේදී අපිට මුහුණ දෙන්න වෙන පොදු ගැටලු කිහිපයක් තියෙනවා:
- Loading States: දත්ත ලැබෙනකල් UI එකට මොකක්ද පෙන්වන්නේ කියලා handle කරන්න ඕනේ. (අපි මේ උදාහරණයේදී ඒක කරලා තියෙනවා.)
- Error Handling: API call එක fail වුණොත් මොකද කරන්නේ? (මේකත් අපි handle කරලා තියෙනවා.)
- Caching: එකම දත්ත නැවත නැවත fetch කරනවා නම්, ඒවා cache කරලා තියාගන්නේ කොහොමද? එහෙම නැතුව හැම වෙලාවෙම අලුතෙන් API call එකක් ගහනවා කියන්නේ server එකටත්, user ගේ internet connection එකටත් බරක්.
- Re-fetching: දත්ත update වුණාම නැවත fetch කරගන්නේ කොහොමද? User කෙනෙක් button එකක් click කරලා refresh කරනවා නම්, නැවත දත්ත fetch කරගන්න සිද්ධ වෙනවා.
- Race Conditions: එකම වෙලාවේ API requests කිහිපයක් ගියොත්, වැරදි පිළිවෙළට data set වෙන්න පුළුවන්.
- Global State Management for Data: Application එකේ තැන් කිහිපයකට එකම දත්ත අවශ්ය වුණොත්, ඒ දත්ත share කරගන්නේ කොහොමද?
මේ ගැටලු තමයි SWR (Stale-While-Revalidate) සහ React Query වගේ library අපිට විසඳලා දෙන්නේ.
SWR සමග Client-Side Data Fetching පහසු කරගනිමු
SWR කියන්නේ Vercel (Next.js හදපු අයම තමයි) විසින් develop කරපු, Client-Side Data Fetching සඳහා React Hooks library එකක්. SWR කියන නම ආවේ HTTP RFC 5861 වල එන “stale-while-revalidate” කියන HTTP cache invalidation strategy එකෙන්. මේකෙන් වෙන්නේ මුලින්ම cache එකේ තියෙන පරණ දත්ත (stale data) පෙන්වලා, background එකේ අලුත් දත්ත (fresh data) fetch කරන එක.
මේකේ වාසි මොනවද?
- Realtime Experience: දත්ත ඉක්මනින් පෙන්වන නිසා user ට හොඳ user experience එකක් ලැබෙනවා.
- Automatic Revalidation: Tab එක මාරු කළාම, network connection එක ආපහු ආවම, හෝ interval එකක් පස්සේ automatic revalidate වෙනවා.
- Caching: ලබාගත් දත්ත cache කරන නිසා නැවත නැවත fetch කරන්න අවශ්ය වෙන්නේ නැහැ.
- Error Handling: Error Handling සහ Loading states auto manage කරනවා.
- Suspense Support: React Suspense එක්කත් වැඩ කරනවා.
හරි, දැන් අපි බලමු SWR install කරලා භාවිතා කරන්නේ කොහොමද කියලා.
SWR Install කිරීම
npm install swr
# or
yarn add swr
SWR භාවිතයෙන් Data Fetching කිරීම
දැන් අපි කලින් හදපු Posts List එක SWR වලින් හදමු. මේකට අපි useSWR
Hook එක භාවිතා කරනවා.
import React from 'react';
import useSWR from 'swr';
// දත්ත fetch කරන function එක. SWR වලට මේක fetcher කියනවා.
const fetcher = async (url) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Failed to fetch data');
}
return response.json();
};
function SWRPostsList() {
// useSWR Hook එකට key එකක් (API URL එක) සහ fetcher function එක දෙනවා.
// SWR automatically data, error, සහ isLoading ලබා දෙනවා.
const { data: posts, error, isLoading } = useSWR('https://jsonplaceholder.typicode.com/posts', fetcher);
if (isLoading) return <p>Posts loading with SWR... ⏳</p>;
if (error) return <p>Error loading posts with SWR: {error.message} ❌</p>;
return (
<div>
<h1>Blog Posts (Fetched with SWR)</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default SWRPostsList;
මේක කලින් useEffect
එකෙන් කරපු එකට වඩා කොච්චර සරලද කියලා බලන්න. SWR වලින් loading
, error
, data
states ටිකත් handle කරනවා. ඒ වගේම data caching, revalidation, retries වගේ දේවලුත් automatically manage කරනවා.
SWR වල Configuration Options
useSWR
Hook එකට තුන්වෙනි argument එකක් විදියට options object එකක් දෙන්න පුළුවන්. මේකෙන් අපිට SWR වල behaviour එක customize කරන්න පුළුවන්.
import React from 'react';
import useSWR from 'swr';
const fetcher = async (url) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Failed to fetch data');
}
return response.json();
};
function ConfiguredSWRPostsList() {
const { data: posts, error, isLoading } = useSWR(
'https://jsonplaceholder.typicode.com/posts',
fetcher,
{
revalidateOnFocus: false, // Tab එක මාරු කළාම revalidate වීම නවත්වනවා
revalidateIfStale: false, // පරණ දත්ත තියෙනවා නම් revalidate වීම නවත්වනවා
revalidateOnReconnect: true, // Network connection එක ආපහු ආවම revalidate වෙනවා
refreshInterval: 5000, // සෑම තත්පර 5කට වරක්ම දත්ත refresh කරනවා
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
if (error.status === 404) return; // 404 නම් retry කරන්න එපා
if (retryCount >= 3) return; // 3 පාරකට වඩා retry කරන්න එපා
setTimeout(() => revalidate(), 5000); // තත්පර 5කට පස්සේ retry කරන්න
},
onSuccess: (data, key, config) => {
console.log('Successfully fetched data for:', key);
}
}
);
if (isLoading) return <p>Posts loading with SWR (Configured)... ⏳</p>;
if (error) return <p>Error loading posts with SWR (Configured): {error.message} ❌</p>;
return (
<div>
<h1>Blog Posts (Fetched with SWR - Configured)</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default ConfiguredSWRPostsList;
මේ විදියට අපිට SWR ගේ behaviour එක අපේ අවශ්යතාවයට අනුව modify කරන්න පුළුවන්. refreshInterval
වගේ options real-time data අවශ්ය තැන්වලට ගොඩක් වැදගත්.
කවදාද Client-Side Rendering (CSR) භාවිතා කළ යුත්තේ?
Next.js වල SSR, SSG වගේ දේවල් තියෙද්දි ඇයි අපි CSR භාවිතා කරන්නේ? සමහර වෙලාවට CSR තමයි හොඳම විසඳුම. මෙන්න මේ වගේ අවස්ථාවලදී:
- User-Specific Data: User කෙනෙක් login වුණාට පස්සේ පෙන්නන dashboards, user profiles, order histories වගේ දේවල්. මේවා හැම user කෙනෙක්ටම වෙනස් නිසා Server-Side එකේ generate කරන්න බැහැ. User login වුණාට පස්සේ client-side එකෙන් දත්ත fetch කරන එක තමයි සුදුසු.
- Real-time Data: Chat applications, stock prices, live scores වගේ දේවල්. මේවා නිරන්තරයෙන් update වෙන නිසා, client-side එකෙන් refresh Interval එකක් එක්ක හෝ WebSockets වගේ දේවල් එක්ක දත්ත ලබාගන්න එක වඩාත් කාර්යක්ෂමයි. SWR වල
refreshInterval
option එක මෙතනදී ගොඩක් වැදගත් වෙනවා. - SEO වැදගත් නොවන Pages/Components: Search Engine Optimization (SEO) කියන එක හැම page එකකටම එතරම් වැදගත් වෙන්නේ නැහැ. උදාහරණයක් විදියට, login page එකක්, admin panel එකක්, හෝ user කෙනෙක් login වුණාට පස්සේ විතරක් දකින්න පුළුවන් private pages වලට SEO එතරම් වැදගත් නැහැ. මේ වගේ තැන්වලට CSR හොඳයි.
- Large Amounts of Data: සමහර වෙලාවට server එකෙන් fetch කරන්න ඕන දත්ත ප්රමාණය ගොඩක් වැඩි වෙන්න පුළුවන්. එහෙම වෙලාවක client-side එකේදී pagination, filtering වගේ දේවල් එක්ක දත්ත ලබාගන්න එක user experience එකටත් හොඳයි, server එකටත් බරක් නැහැ.
- Initial Page Load Speed for Static Content is Primary: සමහර පිටු වල මුලින්ම load වෙන්නේ static content එකක්. ඊට පස්සේ user interactive වුණාම dynamic data ටික load කරනවා. මේක Hydration කියන process එකත් එක්ක සමීපව බැඳිලා තියෙනවා. Next.js SSR/SSG වලින් මුලින්ම HTML එකක් එව්වත්, JavaScript load වෙලා hydration වෙනකල් UI එක interactive නැහැ. SWR/React Query වගේ tools පාවිච්චි කරනකොට මේ hydration issues (JavaScript load වෙනකල් UI එකේ වෙනස්කම් පෙනෙන එක) අඩුකරගන්න පුළුවන්, මොකද data loading සහ UI update එක seamless විදියට manage කරන නිසා.
හොඳම පුරුදු (Best Practices) සහ පොදු ගැටලු
1. සෑම විටම Loading සහ Error States Handle කරන්න.
ඔබ useEffect
පාවිච්චි කරනවා නම් useState
පාවිච්චි කරලා loading
සහ error
states manage කරන්න. SWR/React Query පාවිච්චි කරනවා නම් ඒවා automatically මේවා handle කරන නිසා, ඒ return කරන values (isLoading
, error
) හරියට use කරන්න.
2. Client-Side Data Fetching සඳහා SWR හෝ React Query භාවිතා කරන්න.
සරලම scenarios හැරෙන්න, සැබෑ ලෝකයේ Applications වලට Client-Side Data Fetching සඳහා SWR හෝ React Query (TanStack Query) වගේ Libraries භාවිතා කිරීම අනිවාර්යයෙන්ම කල යුතු දෙයක්. මොකද ඒවා data caching, revalidation, error handling, loading states, optimistic updates වගේ ගොඩක් දේවල් automatically manage කරනවා. මේක ඔබේ development time එකත් අඩු කරනවා වගේම, application එකේ quality එකත් වැඩි කරනවා.
3. API Calls වලට Error Boundaries භාවිතා කරන්න.
විශේෂයෙන්ම production Applications වල, දත්ත ලබාගැනීමේදී සිදුවන unexpected errors වලින් මුළු Application එකම crash නොවී තියාගන්න Error Boundaries භාවිතා කරන්න. මේවා React Components, ඒවායේ child components වල සිදුවන JavaScript errors අල්ලාගෙන, UI එකේ fallback UI එකක් පෙන්වීමට උදව් කරනවා. SWR/React Query වලත් error handling තිබුණත්, global error handling වලට Error Boundaries ගොඩක් වැදගත්.
4. Authentication එක්ක CSR.
User authentication handle කරනකොට, Client-Side Data Fetching වලට token එකක් (e.g., JWT) HTTP request headers වලට එකතු කරන්න සිද්ධ වෙනවා. SWR වලට custom fetcher එකක් දෙන නිසා, ඔබට පහසුවෙන් මේ token එක request එකට add කරන්න පුළුවන්:
const fetcherWithAuth = async (url) => {
const token = localStorage.getItem('authToken'); // හෝ වෙනත් තැනකින් token එක ගන්න.
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Failed to fetch data with authentication');
}
return response.json();
};
// useSWR('protected-api-endpoint', fetcherWithAuth);
5. Network Waterfall Issues අවම කරගන්න.
එක component එකක් දත්ත fetch කරලා, ඒ දත්ත ලැබුනට පස්සේ තව component එකක් දත්ත fetch කරනවා නම් (nested data fetching), මේකෙන් network waterfall එකක් ඇතිවෙන්න පුළුවන්. පුළුවන් නම් parallel requests කරන්න බලන්න. SWR/React Query වලට multiple keys එකම වෙලාවේ pass කරලා parallel fetch කරන්න පුළුවන්.
import useSWR from 'swr';
function Dashboard() {
const { data: userData } = useSWR('/api/user', fetcher);
const { data: ordersData } = useSWR(userData ? `/api/user/${userData.id}/orders` : null, fetcher); // userData ලැබුනොත් විතරක් orders fetch කරන්න.
// ... rest of your component
}
මෙතනදී ordersData
fetch වෙන්නේ userData
ලැබුනට පස්සේ. ඒ වගේම userData
නැත්නම් null
දෙන නිසා request එක යන්නේ නැහැ. මේක තමයි SWR වල conditionally data fetch කරන හැටි.
නිගමනය (Conclusion)
ඉතින් යාලුවනේ, Next.js කියන්නේ SSR, SSG වගේ Server-Side Rendering capabilities වලට ප්රසිද්ධ වුණත්, Client-Side Rendering (CSR) කියන්නේ Next.js Applications වල අත්යාවශ්ය කොටසක්. විශේෂයෙන්ම user-specific data, real-time updates වගේ දේවලට CSR තමයි හොඳම විසඳුම. SWR (හෝ React Query) වගේ data fetching libraries, මේ CSR process එක සරල, කාර්යක්ෂම සහ robust කරනවා. ඒවා caching, revalidation, error handling වගේ දේවල් automatically manage කරන නිසා, ඔබට business logic එක ගැන වැඩියෙන් හිතන්න පුළුවන්.
දැන් ඔබ Client-Side Rendering (CSR) ගැන, useEffect
, fetch
වගේම SWR වගේ බලවත් tool එකක් ගැනත් හොඳ අවබෝධයක් ලබාගෙන ඇති කියලා මම හිතනවා. මේ concepts ඔබේ Next.js projects වලට apply කරලා බලන්න. ඒ වගේම, මේ ලිපිය ගැන ඔබේ අදහස්, ප්රශ්න, හෝ මේ සම්බන්ධව ඔබ මුහුණ දුන් අත්දැකීම් පහලින් comment කරන්න. අපි එකතු වෙලා තවත් දේවල් ඉගෙන ගනිමු!