YouTip LogoYouTip

React Blog Useeffect

\\ In this chapter, you will learn about React's most important side effect Hookβ€”useEffect, and load blog data from a JSON file using fetch at the appropriate time.\\ \\ * * *\\ \\ ## What are Side Effects?\\ \\ In React, side effects refer to operations that are unrelated to rendering:\\ \\ * Requesting data from a server\\ * Operating localStorage\\ * Setting timers with setInterval\\ * Manually modifying the DOM\\ * Subscribing to external events\\ \\ Side effects cannot be executed directly in the component function body (they would execute on every render), and must be placed inside useEffect.\\ \\ * * *\\ \\ ## Basic Usage of useEffect\\ \\ ## Example\\ \\ import{ useState, useEffect } from 'react'\\ \\ function HomePage(){\\ \\ const[message, setMessage]= useState('Loading...')\\ \\ // useEffect(fn, deps):Perform side effects after the component renders\\ \\ useEffect(()=>{\\ \\ console.log('The component has been mounted to the DOM, and side effects can now be executed')\\ \\ setMessage('Data loaded!')\\ \\ },[])// Empty dependency array = Execute only once after the first render\\ \\ return

{message}

\\ \\ }\\ \\ ### Three Ways to Write the Dependency Array\\ \\ | Writing | Execution Time | Use Case |\\ | --- | --- | --- |\\ | `useEffect(fn)` | Executes after every render | Rarely used, easily causes infinite loops |\\ | `useEffect(fn, [])` | Executes only once after the first render | Data loading, initializing third-party libraries |\\ | `useEffect(fn, )` | Executes after first render + when dep changes | Listening for specific data changes, performing responsive operations |\\ \\ > The difference between omitting the dependency array vs an empty array: `useEffect(fn)` executes after every render; `useEffect(fn, [])` executes only once after the first render. The formerEasily causes an infinite loop (effect in setState β†’ Trigger render β†’ Re-execute effect β†’ ...οΌ‰οΌŒAlmost never used.\\ \\ * * *\\ \\ ## Loading JSON Data with fetch\\ \\ Just like Vue3, we put the article data in the `public/posts.json` file.\\ \\ ### Step 1: Create the Data File\\ \\ ## Example\\ \\ // File path: public/posts.json\\ \\ [\\ \\ {\\ \\ "id": 1,\\ \\ "title": "React Getting StartedComplete Guide",\\ \\ "summary": "Learn React Hooks from scratch, covering core concepts like useState, useEffect, etc.",\\ \\ "content": "

Why learn React?

React is one of the most popular frontend frameworks today...

",\\ \\ "category": "React",\\ \\ "date": "2024-05-10"\\ \\ },\\ \\ {\\ \\ "id": 2,\\ \\ "title": "JavaScript Asynchronous Programming Explained",\\ \\ "summary": "Understand Promise, async/await, event loop, and microtask queue in one article.",\\ \\ "content": "

What is asynchronous?

JS is single-threaded...

",\\ \\ "category": "JavaScript",\\ \\ "date": "2024-05-08"\\ \\ },\\ \\ {\\ \\ "id": 3,\\ \\ "title": "CSS Grid Layout in Practice",\\ \\ "summary": "Use CSS Grid Easily implement complex responsive layouts.",\\ \\ "content": "

Grid Getting Started

Grid is a two-dimensional layout system...

",\\ \\ "category": "CSS",\\ \\ "date": "2024-05-05"\\ \\ }\\ \\ ]\\ \\ ### Step 2: Load Data in useEffect\\ \\ ## Example\\ \\ // File path: src/pages/HomePage.jsx\\ \\ import{ useState, useEffect, useMemo } from 'react'\\ \\ import BlogCard from '../components/BlogCard'\\ \\ import CategoryFilter from '../components/CategoryFilter'\\ \\ function HomePage(){\\ \\ const[articles, setArticles]= useState([])// Article data\\ \\ const[isLoading, setIsLoading]= useState(true)// Loading state\\ \\ const[error, setError]= useState(null)// Error message\\ \\ const[activeCategory, setActiveCategory]= useState('All')\\ \\ // useEffect Load data: Empty dependency array = Execute only once after the first render\\ \\ useEffect(()=>{\\ \\ let cancelled =false// Flag to prevent setState after component unmount\\ \\ async function fetchPosts(){\\ \\ setIsLoading(true)\\ \\ setError(null)\\ \\ try{\\ \\ const res = await fetch('/posts.json')\\ \\ if(!res.ok)throw new Error(`HTTP ${res.status}`)\\ \\ const data = await res.json()\\ \\ if(!cancelled){\\ \\ setArticles(data)\\ \\ }\\ \\ }catch(err){\\ \\ if(!cancelled){\\ \\ setError(err.message)\\ \\ }\\ \\ }finally{\\ \\ if(!cancelled){\\ \\ setIsLoading(false)\\ \\ }\\ \\ }\\ \\ }\\ \\ fetchPosts()\\ \\ // Cleanup function: Set cancelled to true on component unmount\\ \\ return()=>{ cancelled =true}\\ \\ },[])\\ \\ const categories = useMemo(()=>{\\ \\ return['All', ...new Set(articles.map(a => a.category))]\\ \\ },)\\ \\ const filteredArticles = useMemo(()=>{\\ \\ if(activeCategory ==='All')return articles\\ \\ return articles.filter(a => a.category=== activeCategory)\\ \\ },[articles, activeCategory])\\ \\ return(\\ \\
\\ \\

Latest Posts

\\ \\ {/* Loading */}\\ \\ {isLoading &&

Loading,Please wait...

}\\ \\ {/* Loading error */}\\ \\ {error &&(\\ \\
\\ \\

Load failed:{error}

\\ \\ \\ \\
\\ \\ )}\\ \\ {/* Data loading complete */}\\ \\ {!isLoading &&!error &&(\\ \\

Total {filteredArticles.length} posts

\\ \\ {filteredArticles.length===0?(\\ \\

No Posts in This Category

\\ \\ ):(\\ \\
\\ \\ {filteredArticles.map(article =>(\\ \\ ))}\\ \\
\\ \\ )}\\ \\ \\ \\ )\\ \\ }\\ \\ export default HomePage\\ \\ > The `cancelled` flag is a common pattern in React. When the fetch is still in progress, if the user leaves the page (component unmounts), subsequent setState calls will cause warning errors. Setting `cancelled = true` in the cleanup function can skip setState after unmounting.\\ \\ * * *\\ \\ ## Cleanup Function\\ \\ The callback function of useEffect can return a function, called the cleanup function.\\ \\ It executes at two times: when the component unmounts and before the next effect executes.\\ \\ ## Example\\ \\ useEffect(()=>{\\ \\ // Side Effect: Subscribe to events\\ \\ const handleScroll =()=> console.log('Scrolled')\\ \\ window.addEventListener('scroll', handleScroll)\\ \\ // Return cleanup function\\ \\ return()=>{\\ \\ // Automatically remove event listeners on component unmount to prevent memory leaks\\ \\ window.removeEventListener('scroll', handleScroll)\\ \\ }\\ \\ },[])\\ \\ useEffect(()=>{\\ \\ // Side Effect: Set a timer\\ \\ const timer = setInterval(()=>{\\ \\ console.log('Execute every second')\\ \\ },1000)\\ \\ return()=> clearInterval(timer)// Clean up timer\\ \\ },[])\\ \\ | Side Effect | Needs Cleanup? | Cleanup Method |\\ | --- | --- | --- |\\ | fetch requests | Yes | Use cancelled flag or AbortController |\\ | Event listeners | Yes | removeEventListener |\\ | Timers | Yes | clearInterval / clearTimeout |\\ | Restoring after DOM modification | Yes | Restore original state in cleanup |\\ | localStorage writes | No | No cleanup needed |\\ \\ * * *\\ \\ ## Handling Four States of Async Requests\\ \\ Any data request should cover these four UI states:\\ \\ | State | Condition | UI |\\ | --- | --- | --- |\\ | Loading | isLoading === true | Loading animation, skeleton screen |\\ | Success | Data has returned | Normal content rendering |\\ | Failure | error !== null | Error message + retry button |\\ | Empty Data | Data is an empty array | Empty state message |\\ \\ * * *\\ \\ ## Comparison with Vue3 Lifecycle\\ \\ | Vue3 | React | Description |\\ | --- | --- | --- |\\ | `onMounted` | `useEffect(fn, [])` | Executes after first render |\\ | `watch(keyword, fn)` | `useEffect(fn, )` | Responds to specific data changes |\\ | `onBeforeUnmount` | `useEffect cleanup` | Cleanup before component destruction |\\ | No direct equivalent | `useEffect(() => { fn; return cleanup }, )` | Cleanup first, then fn when dep changes |\\ \\ * * *\\ \\ ## Chapter Summary\\ \\ In this chapter, you mastered the core usage of useEffect: the three ways to write dependency arrays, loading data asynchronously with fetch, handling four UI states, and the role of the cleanup function.\\ \\ Now the blog data is dynamically loaded from an external JSON file, no longer hardcoded in JS.
← React Blog Custom HooksReact Blog Props β†’