CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-styletron-react

React bindings for Styletron CSS-in-JS toolkit providing styled components and hooks

Pending
Overview
Eval results
Files

context-provider.mddocs/

Context and Provider

Context system for providing Styletron engine instances to styled components and hooks throughout the React component tree. The Provider component is essential for all Styletron React functionality.

Capabilities

Provider Component

Provides Styletron engine instance to all styled components and useStyletron hooks in the component tree.

/**
 * Provides Styletron engine instance to styled components and hooks
 * @param props.children - React children that will have access to the engine
 * @param props.value - Styletron engine instance (StandardEngine)
 * @param props.debugAfterHydration - Enable debug mode after SSR hydration (optional)
 * @param props.debug - Debug engine instance for development tools (optional)
 */
const Provider: React.ComponentType<{
  children: React.ReactNode;
  value: StandardEngine;
  debugAfterHydration?: boolean;
  debug?: DebugEngine;
}>;

Basic Usage:

import React from "react";
import { Provider, styled } from "styletron-react";
import { Client } from "styletron-engine-atomic";

// Create Styletron engine
const engine = new Client();

const StyledButton = styled("button", {
  backgroundColor: "blue",
  color: "white",
  padding: "8px 16px",
});

function App() {
  return (
    <Provider value={engine}>
      <div>
        <h1>My App</h1>
        <StyledButton>Click me</StyledButton>
      </div>
    </Provider>
  );
}

Server-Side Rendering (SSR)

import React from "react";
import { renderToString } from "react-dom/server";
import { Provider, styled } from "styletron-react";
import { Server } from "styletron-engine-atomic";

// Server-side engine
const engine = new Server();

const App = () => (
  <Provider value={engine}>
    <styled.div $style={{ color: "red" }}>
      SSR Content
    </styled.div>
  </Provider>
);

// Render on server
const html = renderToString(<App />);

// Get generated CSS
const css = engine.getCss();

// Send both HTML and CSS to client
const fullHtml = `
  <html>
    <head>
      <style>${css}</style>
    </head>
    <body>
      <div id="root">${html}</div>
    </body>
  </html>
`;

Client-Side Hydration

import React from "react";
import { hydrateRoot } from "react-dom/client";
import { Provider, styled } from "styletron-react";
import { Client } from "styletron-engine-atomic";

// Client-side engine with SSR hydration
const engine = new Client({
  hydrate: document.getElementsByTagName("style"),
});

const App = () => (
  <Provider value={engine}>
    <styled.div $style={{ color: "red" }}>
      Hydrated Content
    </styled.div>
  </Provider>
);

// Hydrate on client
const container = document.getElementById("root");
hydrateRoot(container, <App />);

Development Mode with Debug

import React from "react";
import { Provider, styled, DebugEngine } from "styletron-react";
import { Client } from "styletron-engine-atomic";

const engine = new Client();
const debugEngine = new DebugEngine();

const StyledComponent = styled("div", {
  padding: "16px",
  backgroundColor: "lightblue",
});

function App() {
  return (
    <Provider 
      value={engine}
      debug={debugEngine}
      debugAfterHydration={false}
    >
      <StyledComponent>
        Debug-enabled component
      </StyledComponent>
    </Provider>
  );
}

Multiple Providers

import React from "react";
import { Provider, styled } from "styletron-react";
import { Client } from "styletron-engine-atomic";

// Different engines for different parts of the app
const mainEngine = new Client();
const isolatedEngine = new Client();

const MainButton = styled("button", { backgroundColor: "blue" });
const IsolatedButton = styled("button", { backgroundColor: "red" });

function App() {
  return (
    <Provider value={mainEngine}>
      <div>
        <h1>Main App</h1>
        <MainButton>Main Button</MainButton>
        
        {/* Nested provider with different engine */}
        <Provider value={isolatedEngine}>
          <div>
            <h2>Isolated Section</h2>
            <IsolatedButton>Isolated Button</IsolatedButton>
          </div>
        </Provider>
      </div>
    </Provider>
  );
}

Engine Types

Standard Engine Interface

interface StandardEngine {
  /**
   * Renders a style object to CSS class name
   * @param styleObject - Style object to render
   * @returns CSS class name string
   */
  renderStyle(styleObject: StyleObject): string;
  
  /**
   * Renders keyframes animation to CSS
   * @param keyframes - Keyframes object
   * @returns Animation name string
   */
  renderKeyframes(keyframes: KeyframesObject): string;
  
  /**
   * Renders font face declaration to CSS
   * @param fontFace - Font face object
   * @returns Font family name string
   */
  renderFontFace(fontFace: FontFaceObject): string;
}

Debug Engine

class DebugEngine {
  /**
   * Creates debug information for styled components
   * @param options - Debug options including stack information
   * @returns Debug class name for development tools
   */
  debug(options: {
    stackInfo: {
      stack: any;
      message: any;
    };
    stackIndex: number;
  }): string | undefined;
}

Error Handling

No Engine Provided

When no Provider is found in the component tree, Styletron React will use a no-op engine and show a warning in development mode:

// This will trigger a warning in development
function ComponentWithoutProvider() {
  const StyledDiv = styled("div", { color: "red" });
  
  return <StyledDiv>No provider found</StyledDiv>;
  // Warning: "Styletron Provider is not set up. Defaulting to no-op."
}

Engine Compatibility

Ensure the engine implements the StandardEngine interface:

import { Client, Server } from "styletron-engine-atomic";

// ✅ Compatible engines
const clientEngine = new Client();
const serverEngine = new Server();

// ❌ Incompatible - missing required methods
const invalidEngine = {
  renderStyle: () => "class-name",
  // Missing renderKeyframes and renderFontFace
};

Provider Props

interface ProviderProps {
  /** React children components */
  children: React.ReactNode;
  
  /** Styletron engine instance implementing StandardEngine interface */
  value: StandardEngine;
  
  /** 
   * Enable debug mode after SSR hydration (optional)
   * Useful for avoiding hydration mismatches in development
   */
  debugAfterHydration?: boolean;
  
  /** 
   * Debug engine instance for development tools (optional)
   * Only used in development mode for debugging and devtools integration
   */
  debug?: DebugEngine;
}

Best Practices

Single Provider Pattern

Use one Provider at the root of your application:

// ✅ Recommended
function App() {
  return (
    <Provider value={engine}>
      <Router>
        <Routes>
          <Route path="/" component={Home} />
          <Route path="/about" component={About} />
        </Routes>
      </Router>
    </Provider>
  );
}

Engine Initialization

Initialize engines outside of render functions:

// ✅ Initialize outside component
const engine = new Client();

function App() {
  return <Provider value={engine}>...</Provider>;
}

// ❌ Avoid initializing inside component
function App() {
  const engine = new Client(); // Creates new engine on every render
  return <Provider value={engine}>...</Provider>;
}

Development vs Production

Use different configurations for development and production:

const isDevelopment = process.env.NODE_ENV === "development";

const engine = new Client({
  prefix: isDevelopment ? "dev_" : "",
});

const debugEngine = isDevelopment ? new DebugEngine() : undefined;

function App() {
  return (
    <Provider 
      value={engine} 
      debug={debugEngine}
      debugAfterHydration={isDevelopment}
    >
      <AppContent />
    </Provider>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-styletron-react

docs

component-composition.md

context-provider.md

core-styling.md

index.md

react-hooks.md

tile.json