ESLint Plugin for React Server Components
eslint-plugin-react-server-components is an ESLint plugin providing rules specifically designed to manage and enforce the correct usage of React Server Components (RSCs) and Client Components. As of version 1.2.0, this plugin helps developers identify components that incorrectly mix server-side and client-side logic, primarily by ensuring that components using client-only features (like `useState`, `useEffect`, or browser APIs) are correctly prefixed with the `"use client"` directive. It also helps detect instances where `"use client"` might be unnecessarily applied. The plugin features a `recommended` configuration for easy setup and offers options like `allowedServerHooks` (introduced in v1.2.0) to whitelist specific hooks that should not trigger errors in server components. With regular patch and minor releases, the project appears to be actively maintained, adapting to the evolving best practices for RSCs, particularly relevant for frameworks like Next.js that heavily utilize this paradigm. Its key differentiation lies in its focused approach to linting the specific contract between server and client components.
Common errors
-
Parsing error: The keyword 'await' is reserved
cause ESLint parser not configured for modern JavaScript/JSX features or module syntax used in React Server Components or client components.fixEnsure your ESLint configuration includes a parser like `@babel/eslint-parser` or `@typescript-eslint/parser` and appropriate `ecmaVersion` (`'latest'`) and `sourceType` (`'module'`) settings to support JSX and ES modules. -
eslint-plugin-react-server-components/use-client: Components must be prefixed with 'use client' or be a server component.
cause A component intended for client-side use (e.g., using `useState`, `useEffect`, or browser APIs) lacks the `"use client"` directive at the top of its file.fixAdd `"use client"` as the very first line of the file for components that utilize client-only features. Alternatively, if it's meant to be a server component, remove any client-only hooks or APIs from it. -
Configuration for rule 'react-server-components/use-client' is invalid
cause Misspelling `allowedServerHooks` or providing it with an incorrect data type or structure within the rule's options.fixDouble-check the `allowedServerHooks` option name for correct capitalization and ensure it is provided as an array within an object, which is then nested as the second element in the rule's configuration array (e.g., `['error', { 'allowedServerHooks': ['myCustomHook'] }]`).
Warnings
- breaking Class components are now disallowed by the plugin, likely due to their incompatibility with the React Server Components paradigm unless explicitly marked 'use client'.
- gotcha Incorrect placement of the `"use client"` directive (e.g., after comments or other statements) can lead to the rule failing to detect it, causing unexpected errors or silent misinterpretations of component types.
- gotcha Failing to extend the `recommended` configuration or incorrectly naming the plugin in your `.eslintrc` can lead to rules not being applied, resulting in silently unlinted code.
Install
-
npm install eslint-plugin-react-server-components -
yarn add eslint-plugin-react-server-components -
pnpm add eslint-plugin-react-server-components
Imports
- Configuration via `extends`
{ "extends": ["react-server-components/recommended"] }{ "extends": ["plugin:react-server-components/recommended"] } - Individual Rule `use-client`
{ "rules": { "use-client": "error" } }{ "rules": { "react-server-components/use-client": "error" } } - Configuring `allowedServerHooks` option
{ "allowedServerHooks": ["useTranslation"], "rules": { "react-server-components/use-client": "error" } }{ "rules": { "react-server-components/use-client": [ "error", { "allowedServerHooks": ["useTranslation"] } ] } }
Quickstart
import React from 'react';
// This component uses client-side state without the 'use client' directive.
// This ESLint plugin would flag this as an error under its recommended ruleset.
function MyClientComponent() {
const [count, setCount] = React.useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
export default MyClientComponent;
// To lint this file, you would run:
// npm install --save-dev eslint eslint-plugin-react-server-components
// Create an .eslintrc.json file:
// {
// "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" },
// "extends": ["plugin:react-server-components/recommended"]
// }
// Then run: npx eslint myClientComponent.jsx