article

Monday, January 6, 2025

React.js Data Fetching With React SWR

React.js Data Fetching With React SWR
React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app

Run
C:\react-js\my-app> npm start
npm i react-router-dom
https://www.npmjs.com/package/react-router-dom

Install React SWR:
npm i swr
https://www.npmjs.com/package/swr
src\App.js
//src\App.js
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import PostList from "./elements/PostList";
import PostDetails from "./elements/PostDetails";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/postswr" element={<PostList />} />
        <Route path="/post-detail/:postId" element={<PostDetails />} />
      </Routes>
    </BrowserRouter>
  );
}
 
export default App;
src\elements\Home.js
//src\elements\Home.js
import React  from 'react';
import Posts from './Posts'
import { Suspense } from "react";

function Home() {

  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">Basic example fetch dummy data</h1>
        </div> 
        <div className="overflow-x-auto py-10">
            <Suspense fallback="Loading...">
                <Posts/> 
            </Suspense>
        </div>
    </div>
  )
}

export default Home
src\elements\Posts.js
//src\elements\Posts.js
import { useEffect, useState } from "react";
const base_url = 'https://dummyjson.com';

function Post() {
    const [posts, setPosts] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);
    useEffect(() => {
        const fetchData = async (url) => {
            setIsLoading(true);
            try {
                const data = await fetch(base_url + url)
                .then(res => res.json());
                setPosts(data ? data.posts : []);
            } catch(error) {
                setError('Failed to load');
            }
            
            setIsLoading(false);
        }
        fetchData('/posts');
    }, []);

    return (
        <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
            {
                error ? <div>{error}</div> : null
            }
            {
                isLoading ? <div>loading...</div> : null
            }
            {
                posts ? posts.map(post => {
                    return (
                        <div key={post.id} className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                            <h3><a>{post.title}</a></h3>
                            <p>{post.body}</p>
                            <span>Views: {post.views}</span>
                            <div>Tags: {post.tags.map(tag => <span key={tag}>{tag}</span>)}</div>
                        </div>
                    )
                }) : null
            }
        </div>
    );
}

export default Post;
src\elements\PostList.js
//src\elements\PostList.js
import React from "react";
import { Link } from "react-router-dom";
import useSWR from 'swr'; //npm i swr https://www.npmjs.com/package/swr

function PostList()
{
    const base_url = 'https://dummyjson.com';

    const fetcher = (url) => {
        return fetch(base_url + url).then(res => res.json());
    };

    const { data, error, isLoading } = useSWR('/posts', fetcher);

    const style = {margin: '2px', background: '#000000', padding: '2px 7px', borderRadius: '6px'};

    return (
        <div className="w-screen py-20 flex justify-center flex-col items-center">
            <div className="flex items-center justify-between gap-1 mb-5">
                <h1 className="text-4xl font-bold">React.js Data Fetching With React SWR</h1>
            </div> 
            <div className="overflow-x-auto py-1">
                <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
                    {
                        error ? <div>failed to load</div> : null
                    }

                    {
                        isLoading ? <div>loading...</div> : null
                    }

                    {
                        data ? data.posts.map(post => {
                            return (
                                <div key={post.id} className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                                    <h3><Link to={`/post-detail/${post.id}`}>{post.title}</Link></h3>
                                    <p>{post.body}</p>
                                    <span>Views: {post.views}</span>
                                    <div>Tags: {post.tags.map(tag => <span key={tag} style={style}>{tag}</span>)}</div>
                                </div>
                            )
                        }) : null
                    }
                </div>
            </div>
        </div>        
    )
}

export default PostList
src\elements\PostDetails.js
//src\elements\PostDetails.js
import React from "react";
import { useParams } from 'react-router-dom';
import useSWR from 'swr';

const base_url = 'https://dummyjson.com';

function PostDetails()
{
    let { postId } = useParams();

    const fetcher = async ([url, postId]) => {

        const res = await fetch(base_url + url + `/${postId}`);

        if (!res.ok) {
            const error = new Error('An error occurred while fetching the data.')
            error.status = res.status
            throw error
          }
         
          return res.json()
    }

    const { data: post, error,  isLoading } = useSWR(['/posts', postId], fetcher);

    const style = {margin: '2px', background: '#d7d4d4', padding: '2px 7px', borderRadius: '6px'};

    return (
        <div className='w-1/2 py-10 m-auto flex justify-between items-center align-middle flex-wrap gap-10'>
            {
                error ? <div>{error.message}</div> : null
            }

            {
                isLoading ? <div>loading...</div> : null
            }

            {
                post && (
                    <div className='btn-primary p-2 bg-blue-500 text-white text-lg rounded-lg hover:shadow-lg disabled:opacity-50'>
                            <h3>{post.title}</h3>
                            <p>{post.body}</p>
                            <span>Views: {post.views}</span>
                            <div>Tags: {post.tags.map(tag => <span key={tag} style={style}>{tag}</span>)}</div>
                            <div>Likes: 👍 {post.reactions.likes}</div>
                            <div>Deslikes: 👎 {post.reactions.likes}</div>
                        </div>
                )
            }
        </div>
    )
}

export default PostDetails;
Run C:\react-j\my-app>npm start
http://localhost:3000/

Related Post