-
Notifications
You must be signed in to change notification settings - Fork 49.9k
Description
Overview
This proposal outlines a specification for server-side React code that brings together functional programming principles, declarative side-effects, and intelligent query-based data fetching to improve both developer experience and application performance.
Motivation
Modern server-side rendering approaches often separate data fetching logic from component logic, leading to waterfall requests and tight coupling between components and data sources. This proposal aims to address these challenges by introducing a unified approach that:
- Maintains React's declarative programming model on the server
- Provides performance efficiencies through document-scoped query optimization
- Allows client-side selectivity over response payloads
- Preserves functional programming principles throughout the stack
Key Advantages
1. Functional Programming (FP) Approach
- Pure, composable server components
- Predictable data transformations
- Easier testing and reasoning about server-side logic
2. useEffect Declarative Side-Effects
- Extends React's declarative model to server-side effects
- Unified mental model between client and server
- Explicit dependency tracking for server-side operations
3. Document-Scoped Query Language
- Single query optimization across component tree
- Automatic batching and deduplication of data requests
- Reduces round-trips and over-fetching
- Performance gains similar to GraphQL but integrated into React's component model
4. Client-Side Selectivity on Response Body
- Client can specify which parts of the component tree need data
- Reduces payload size for partial updates
- Enables progressive enhancement and streaming scenarios
Proposed Architecture
Server-Side Component with Query Declaration
// ServerComponent.js
import { useServerQuery, useServerEffect } from 'react-server';
function UserProfile({ userId }) {
// Declarative query - automatically batched and optimized
const user = useServerQuery(query => ({
user: query.user(userId, {
select: ['name', 'email', 'avatar'],
posts: {
select: ['title', 'createdAt'],
limit: 10
}
})
}));
// Server-side effect - runs only on server
useServerEffect(() => {
// Log analytics, update cache, etc.
analytics.track('profile_view', { userId });
}, [userId]);
return (
<div>
<h1>{user.name}</h1>
<Avatar src={user.avatar} />
<PostList posts={user.posts} />
</div>
);
}Client-Side Selective Refetch
// Client can request only specific parts of the tree
import { useSelectiveRefetch } from 'react';
function ClientComponent() {
const refetch = useSelectiveRefetch();
const updatePosts = () => {
// Only refetch the posts portion of UserProfile
refetch('/user-profile', {
select: { posts: true }
});
};
// ...
}Benefits
- Performance: Document-scoped queries eliminate waterfalls and over-fetching
- Developer Experience: Single mental model across client and server
- Type Safety: Query language can be fully typed with TypeScript
- Flexibility: Client controls data granularity for updates
- Optimization: Automatic batching, deduplication, and caching
- Progressive Enhancement: Selective loading enables better perceived performance
Use Cases
- Dashboard applications with complex nested data requirements
- E-commerce product pages with multiple data sources
- Social feeds with selective updates
- Real-time collaborative applications with partial state sync
Open Questions
- How does this integrate with existing React Server Components (RSC)?
- What's the story for TypeScript inference across the query language?
- How should error boundaries work with server-side effects?
- What's the caching strategy for server queries?
- How does this interact with Suspense and streaming SSR?
- Should the query language be extensible for different data sources (REST, GraphQL, databases)?
Next Steps
I'd love to get feedback from the React core team on:
- Whether this aligns with the direction of React Server Components
- Technical feasibility and potential implementation challenges
- Interest in exploring this further as an RFC
I'm happy to elaborate on any aspect of this proposal or provide additional examples.