A React compatibility layer for Preact
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Full React context system for sharing data between components without explicit prop passing.
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>
);
}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>
);
}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>
);
}
}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