React Fela Bindings
react-fela provides the official React bindings for the Fela dynamic styling library. It facilitates CSS-in-JS styling within React applications, leveraging Fela's core capabilities for atomic CSS generation, performance optimization, and server-side rendering. The current stable version is 12.2.1, with a consistent release cadence that includes minor feature additions, TypeScript improvements, and bug fixes across patch versions. Key differentiators include its focus on a functional, atomic CSS approach, robust plugin system (enhanced with context-free plugins in v12), and efficient rehydration mechanisms. It assumes familiarity with the core Fela library for its effective use within a React ecosystem.
Common errors
-
Error: Fela renderer not found. Make sure to wrap your application with `RendererProvider`.
cause The Fela renderer instance was not provided to the React component tree via the `RendererProvider`.fixWrap your root component or the section using Fela styles with `<RendererProvider renderer={myRendererInstance}>...</RendererProvider>`. -
TypeError: Cannot read properties of undefined (reading 'theme')
cause A component attempted to access `theme` from the Fela context, but `ThemeProvider` was not used or the theme object was not provided.fixEnsure your components are wrapped with `<ThemeProvider theme={myThemeObject}>...</ThemeProvider>` and that `myThemeObject` is a valid theme object. -
Module not found: Can't resolve 'fela' in '.../node_modules/react-fela/lib'
cause The core `fela` package, a peer dependency of `react-fela`, is not installed or cannot be resolved by the module bundler.fixInstall the core Fela package by running `npm install fela` or `yarn add fela`.
Warnings
- breaking Fela v12 introduced significant architectural changes, including a new context-free plugin concept and rehydration improvements. This requires migration for applications upgrading from Fela v11 or earlier.
- gotcha Fela v12.0.0 had a bug that accidentally passed an extra `theme` attribute to elements, potentially causing unexpected behavior or rendering issues. This was addressed in a hotfix.
- breaking Prior to Fela v11.6.0, the `RendererProvider` component had a `Children.only` restriction, meaning it could only accept a single child. This could lead to runtime errors if multiple children were provided.
- gotcha Ensure `fela` is installed as a direct dependency or peer dependency that satisfies the `react-fela` version requirements. `react-fela` provides bindings, but the core Fela library is essential for styling to function.
Install
-
npm install react-fela -
yarn add react-fela -
pnpm add react-fela
Imports
- useFela
import useFela from 'react-fela'
import { useFela } from 'react-fela' - RendererProvider
const { RendererProvider } = require('react-fela')import { RendererProvider } from 'react-fela' - ThemeProvider
import { ThemeProvider as FelaThemeProvider } from 'react-fela'import { ThemeProvider } from 'react-fela' - createRenderer
import { createRenderer } from 'react-fela'import { createRenderer } from 'fela'
Quickstart
import { createRenderer } from 'fela';
import { RendererProvider, ThemeProvider, useFela } from 'react-fela';
import { useState } from 'react';
const renderer = createRenderer();
const theme = {
primary: 'blue',
secondary: 'green',
spacing: 16,
};
type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
};
const Button: React.FC<ButtonProps> = ({ onClick, children }) => {
const { css } = useFela((props: { primaryColor: string }) => ({
button: {
backgroundColor: props.primaryColor,
color: 'white',
padding: `${theme.spacing / 2}px ${theme.spacing}px`,
borderRadius: '4px',
border: 'none',
cursor: 'pointer',
fontSize: '16px',
'&:hover': {
opacity: 0.8,
},
},
}));
return (
<button className={css('button', { primaryColor: theme.primary })} onClick={onClick}>
{children}
</button>
);
};
const App: React.FC = () => {
const [count, setCount] = useState(0);
return (
<RendererProvider renderer={renderer}>
<ThemeProvider theme={theme}>
<div style={{ fontFamily: 'sans-serif', padding: theme.spacing }}>
<h1>Fela with React Example</h1>
<p>Count: {count}</p>
<Button onClick={() => setCount(prev => prev + 1)}>Increment</Button>
<div className={useFela(() => ({
marginTop: theme.spacing,
color: theme.secondary,
fontSize: '14px'
}))().css({})}>
Styled with `useFela` hook directly on a div.
</div>
</div>
</ThemeProvider>
</RendererProvider>
);
};
export default App;