Async Posts List
Difficulty: Advanced
Problem Statement
Fetch posts on mount, show loading, render list, support filter action, handle failures gracefully.
Live Demo
Try the running app below — this is the target behavior for the challenge.
Async Posts List — Live Demo
Loading…
What Interviewers Expect
- Loading/error/success branches.
- Effect cleanup with mounted flag or abort.
- Test-friendly selectors (
data-testid).
Step-by-Step Implementation
Step 1 — Async effect
Fetch on mount and guard setState after unmount.
useEffect(() => { let mounted = true; ... return () => { mounted = false; }; }, []);
Step 2 — Loading UI
Render loading state until data arrives.
if (!posts) return <p>Loading…</p>;
Step 3 — Filter action
Support user action to slice visible posts.
const visible = filtered ? posts.slice(0, 2) : posts;
Complete Implementation
Copy-paste ready single-file solution. Use this as your reference after attempting the challenge yourself, or paste it into CodeSandbox / StackBlitz to run locally.
App.jsx
import React, {useEffect, useState} from 'react';
const MOCK_POSTS = [
{id: 1, title: 'React state basics'},
{id: 2, title: 'Machine coding tips'},
{id: 3, title: 'Testing async UI'},
{id: 4, title: 'Transfer list patterns'},
];
export default function App() {
const [posts, setPosts] = useState(null);
const [error, setError] = useState('');
const [filtered, setFiltered] = useState(false);
useEffect(() => {
let mounted = true;
const timer = setTimeout(() => {
if (mounted) setPosts(MOCK_POSTS);
}, 700);
return () => {
mounted = false;
clearTimeout(timer);
};
}, []);
if (error) return <p>{error}</p>;
if (!posts) return <p>Loading…</p>;
const visible = filtered ? posts.slice(0, 2) : posts;
return (
<div>
<button type="button" onClick={() => setFiltered(true)}>
Filter first 2
</button>
<ul data-testid="list">
{visible.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
Final Checklist
- UI works for primary flow
- Edge cases handled (empty/disabled/loading where relevant)
- State updates are immutable
- Components are readable and reasonably split
- You can explain trade-offs out loud in an interview
Next Challenge
Continue to the next item in the sidebar when you're comfortable implementing this from scratch in 30–45 minutes.