React 18 introduces concurrent rendering for smoother user experiences. Combined with Laravel APIs, it creates powerful full-stack applications. At ZIRA Software, React 18 concurrent features transformed our application responsiveness.
Setup with Laravel
# Create React app
npm create vite@latest frontend -- --template react-ts
cd frontend
npm install
# Install React 18
npm install react@18 react-dom@18
// main.tsx - Concurrent root
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container!);
root.render(<App />);
Automatic Batching
// React 17: Multiple re-renders
setCount(c => c + 1);
setFlag(f => !f);
// Two renders
// React 18: Automatic batching
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// Single render!
}
// Works in async too
async function fetchData() {
const data = await api.get('/users');
setUsers(data.users);
setLoading(false);
// Single render!
}
Transitions
import { useState, useTransition } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
function handleSearch(e) {
const value = e.target.value;
// Urgent: Update input immediately
setQuery(value);
// Non-urgent: Can be interrupted
startTransition(() => {
fetchResults(value).then(setResults);
});
}
return (
<div>
<input value={query} onChange={handleSearch} />
{isPending && <Spinner />}
<ResultsList results={results} />
</div>
);
}
Suspense for Data Fetching
import { Suspense } from 'react';
import { useQuery } from '@tanstack/react-query';
// Data fetching component
function UserProfile({ userId }) {
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
suspense: true,
});
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// Parent with Suspense boundary
function App() {
return (
<Suspense fallback={<ProfileSkeleton />}>
<UserProfile userId={1} />
</Suspense>
);
}
Nested Suspense Boundaries
function Dashboard() {
return (
<div className="dashboard">
<Suspense fallback={<HeaderSkeleton />}>
<Header />
</Suspense>
<div className="content">
<Suspense fallback={<SidebarSkeleton />}>
<Sidebar />
</Suspense>
<main>
<Suspense fallback={<PostsSkeleton />}>
<Posts />
<Suspense fallback={<CommentsSkeleton />}>
<Comments />
</Suspense>
</Suspense>
</main>
</div>
</div>
);
}
useDeferredValue
import { useState, useDeferredValue, memo } from 'react';
function SearchResults({ query }) {
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
return (
<div style={{ opacity: isStale ? 0.5 : 1 }}>
<ResultsList query={deferredQuery} />
</div>
);
}
// Expensive component
const ResultsList = memo(function ResultsList({ query }) {
const results = useSearchResults(query);
return (
<ul>
{results.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
});
Laravel API Integration
// app/Http/Controllers/Api/PostController.php
class PostController extends Controller
{
public function index(Request $request)
{
$posts = Post::query()
->when($request->search, function ($query, $search) {
$query->where('title', 'like', "%{$search}%");
})
->with('author:id,name')
->paginate(20);
return PostResource::collection($posts);
}
}
// React component
function PostList() {
const [search, setSearch] = useState('');
const deferredSearch = useDeferredValue(search);
const { data: posts } = useQuery({
queryKey: ['posts', deferredSearch],
queryFn: () =>
fetch(`/api/posts?search=${deferredSearch}`)
.then(r => r.json()),
suspense: true,
});
return (
<div>
<input
value={search}
onChange={e=> setSearch(e.target.value)}
placeholder="Search posts..."
/>
<Suspense fallback={<PostsSkeleton />}>
<PostGrid posts={posts.data} />
</Suspense>
</div>
);
}
Conclusion
React 18 concurrent features with Laravel backends create responsive, modern applications. Suspense, transitions, and automatic batching improve user experience significantly.
Building React 18 applications? Contact ZIRA Software for full-stack development.