Skip to content

[Proposal] Server-Side React Specification with Declarative Side-Effects and Query-Based Selectivity #35072

@phitonias

Description

@phitonias

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

  1. Performance: Document-scoped queries eliminate waterfalls and over-fetching
  2. Developer Experience: Single mental model across client and server
  3. Type Safety: Query language can be fully typed with TypeScript
  4. Flexibility: Client controls data granularity for updates
  5. Optimization: Automatic batching, deduplication, and caching
  6. 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

  1. How does this integrate with existing React Server Components (RSC)?
  2. What's the story for TypeScript inference across the query language?
  3. How should error boundaries work with server-side effects?
  4. What's the caching strategy for server queries?
  5. How does this interact with Suspense and streaming SSR?
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: UnconfirmedA potential issue that we haven't yet confirmed as a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions