CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-preact-compat

A React compatibility layer for Preact

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

context-api.mddocs/

Context API

Full React context system for sharing data between components without explicit prop passing.

Capabilities

Create Context

Creates a context object with Provider and Consumer components for sharing data across the component tree.

/**
 * Create a context object for sharing data between components
 * @param {any} defaultValue - Default value when no Provider is found
 * @returns {Context} Context object with Provider and Consumer components
 */
function createContext(defaultValue);

/**
 * Context object with Provider and Consumer components
 */
interface Context<T> {
  /**
   * Provider component that supplies context value to descendants
   */
  Provider: ComponentClass<{
    value: T;
    children?: ComponentChildren;
  }>;
  
  /**
   * Consumer component that consumes context value
   */
  Consumer: ComponentClass<{
    children: (value: T) => ComponentChildren;
  }>;
}

Usage Examples:

import { createContext, Component } from 'preact-compat';

// Create context
const ThemeContext = createContext('light');

// Provider component
class ThemeProvider extends Component {
  state = { theme: 'dark' };
  
  toggleTheme = () => {
    this.setState(prevState => ({
      theme: prevState.theme === 'light' ? 'dark' : 'light'
    }));
  };
  
  render() {
    return (
      <ThemeContext.Provider value={{
        theme: this.state.theme,
        toggleTheme: this.toggleTheme
      }}>
        {this.props.children}
      </ThemeContext.Provider>
    );
  }
}

// Consumer component
function ThemedButton() {
  return (
    <ThemeContext.Consumer>
      {({ theme, toggleTheme }) => (
        <button 
          className={`btn btn-${theme}`}
          onClick={toggleTheme}
        >
          Current theme: {theme}
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

// App structure
function App() {
  return (
    <ThemeProvider>
      <div>
        <h1>My App</h1>
        <ThemedButton />
      </div>
    </ThemeProvider>
  );
}

Multiple Contexts

import { createContext } from 'preact-compat';

// Multiple contexts for different concerns
const UserContext = createContext(null);
const SettingsContext = createContext({});

function App() {
  const user = { name: 'John', id: 1 };
  const settings = { darkMode: true, language: 'en' };
  
  return (
    <UserContext.Provider value={user}>
      <SettingsContext.Provider value={settings}>
        <Dashboard />
      </SettingsContext.Provider>
    </UserContext.Provider>
  );
}

function Dashboard() {
  return (
    <UserContext.Consumer>
      {user => (
        <SettingsContext.Consumer>
          {settings => (
            <div className={settings.darkMode ? 'dark' : 'light'}>
              <h1>Welcome, {user.name}!</h1>
            </div>
          )}
        </SettingsContext.Consumer>
      )}
    </UserContext.Consumer>
  );
}

Context with Class Components

import { createContext, Component } from 'preact-compat';

const ApiContext = createContext();

class ApiProvider extends Component {
  state = {
    data: null,
    loading: false,
    error: null
  };
  
  fetchData = async (url) => {
    this.setState({ loading: true, error: null });
    try {
      const response = await fetch(url);
      const data = await response.json();
      this.setState({ data, loading: false });
    } catch (error) {
      this.setState({ error, loading: false });
    }
  };
  
  render() {
    return (
      <ApiContext.Provider value={{
        ...this.state,
        fetchData: this.fetchData
      }}>
        {this.props.children}
      </ApiContext.Provider>
    );
  }
}

class DataComponent extends Component {
  componentDidMount() {
    // Access context via contextType (not supported in preact-compat)
    // Use Consumer pattern instead
  }
  
  render() {
    return (
      <ApiContext.Consumer>
        {({ data, loading, error, fetchData }) => (
          <div>
            <button onClick={() => fetchData('/api/data')}>
              Load Data
            </button>
            {loading && <p>Loading...</p>}
            {error && <p>Error: {error.message}</p>}
            {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
          </div>
        )}
      </ApiContext.Consumer>
    );
  }
}

Types

interface Context<T> {
  Provider: ComponentClass<ProviderProps<T>>;
  Consumer: ComponentClass<ConsumerProps<T>>;
}

interface ProviderProps<T> {
  value: T;
  children?: ComponentChildren;
}

interface ConsumerProps<T> {
  children: (value: T) => ComponentChildren;
}

type ContextType<C extends Context<any>> = C extends Context<infer T> ? T : never;

Install with Tessl CLI

npx tessl i tessl/npm-preact-compat

docs

children-utilities.md

context-api.md

core-api.md

immutability-helpers.md

index.md

legacy-apis.md

performance-tools.md

refs-system.md

server-rendering.md

transition-groups.md

tile.json