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

performance-tools.mddocs/

Performance Tools

Development and performance utilities including pure render mixins and performance measurement tools.

Capabilities

Pure Render Mixin

Performance optimization mixin that implements shallow comparison for shouldComponentUpdate.

/**
 * Mixin that provides shallow comparison for shouldComponentUpdate
 */
const PureRenderMixin = {
  /**
   * Shallow comparison implementation for props and state
   * @param {object} nextProps - Next props object
   * @param {object} nextState - Next state object
   * @returns {boolean} Whether component should update
   */
  shouldComponentUpdate(nextProps, nextState);
};

Usage Examples:

import { PureRenderMixin } from 'preact-compat';
// or
import PureRenderMixin from 'preact-compat/lib/ReactComponentWithPureRenderMixin';

// With createClass
const OptimizedComponent = createClass({
  mixins: [PureRenderMixin],
  
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.props.content}</p>
      </div>
    );
  }
});

// Manual implementation in ES6 class
class ManualPureComponent extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    return PureRenderMixin.shouldComponentUpdate.call(
      this, 
      nextProps, 
      nextState
    );
  }
  
  render() {
    return <div>{this.props.data}</div>;
  }
}

// Or use PureComponent (recommended)
class BetterPureComponent extends PureComponent {
  render() {
    return <div>{this.props.data}</div>;
  }
}

Performance Measurement (ReactPerf)

Development tools for measuring component performance (no-op implementations in production).

/**
 * Performance measurement utilities (no-op in Preact)
 */
const ReactPerf = {
  /**
   * Start performance measurement
   */
  start(): void;
  
  /**
   * Stop performance measurement
   */
  stop(): void;
  
  /**
   * Check if profiling is currently running
   * @returns {boolean} Always false in Preact
   */
  isRunning(): boolean;
  
  /**
   * Get last measurement data
   * @returns {Array} Empty array in Preact
   */
  getLastMeasurements(): Array<any>;
  
  /**
   * Get exclusive time measurements
   * @param {Array} measurements - Measurement data
   * @returns {Array} Empty array in Preact
   */
  getExclusive(measurements): Array<any>;
  
  /**
   * Get inclusive time measurements
   * @param {Array} measurements - Measurement data
   * @returns {Array} Empty array in Preact
   */
  getInclusive(measurements): Array<any>;
  
  /**
   * Get wasted time measurements
   * @param {Array} measurements - Measurement data
   * @returns {Array} Empty array in Preact
   */
  getWasted(measurements): Array<any>;
  
  /**
   * Get operation measurements
   * @param {Array} measurements - Measurement data
   * @returns {Array} Empty array in Preact
   */
  getOperations(measurements): Array<any>;
  
  /**
   * Print exclusive time measurements (no-op)
   * @param {Array} measurements - Measurement data
   */
  printExclusive(measurements): void;
  
  /**
   * Print inclusive time measurements (no-op)
   * @param {Array} measurements - Measurement data
   */
  printInclusive(measurements): void;
  
  /**
   * Print wasted time measurements (no-op)
   * @param {Array} measurements - Measurement data
   */
  printWasted(measurements): void;
  
  /**
   * Print operation measurements (no-op)
   * @param {Array} measurements - Measurement data
   */
  printOperations(measurements): void;
};

Usage Examples:

import { ReactPerf } from 'preact-compat';
// or
import ReactPerf from 'preact-compat/lib/ReactPerf';

// Performance measurement (no-op in Preact, but compatible API)
if (process.env.NODE_ENV === 'development') {
  // Start profiling
  ReactPerf.start();
  
  // ... perform operations to measure
  
  // Stop profiling and collect results
  ReactPerf.stop();
  const measurements = ReactPerf.getLastMeasurements();
  
  // Print different types of measurements
  ReactPerf.printInclusive(measurements);
  ReactPerf.printExclusive(measurements);
  ReactPerf.printWasted(measurements);
  ReactPerf.printOperations(measurements);
  
  // Check if profiling is running
  console.log('Profiling active:', ReactPerf.isRunning());
}

Transition Event Utilities

Utilities for handling CSS transition and animation events.

/**
 * Add event listener for transition/animation end events
 * @param {Element} node - DOM element
 * @param {function} eventListener - Event handler function
 */
function addEndEventListener(node, eventListener);

/**
 * Remove event listener for transition/animation end events
 * @param {Element} node - DOM element
 * @param {function} eventListener - Event handler function
 */
function removeEndEventListener(node, eventListener);

Usage Examples:

import { 
  addEndEventListener, 
  removeEndEventListener 
} from 'preact-compat/lib/ReactTransitionEvents';

class AnimatedComponent extends Component {
  componentDidMount() {
    const element = this.refs.animatedElement;
    
    // Add transition end listener
    this.handleTransitionEnd = (event) => {
      console.log('Transition completed:', event);
      this.setState({ animationComplete: true });
    };
    
    addEndEventListener(element, this.handleTransitionEnd);
  }
  
  componentWillUnmount() {
    const element = this.refs.animatedElement;
    removeEndEventListener(element, this.handleTransitionEnd);
  }
  
  startAnimation = () => {
    const element = this.refs.animatedElement;
    element.classList.add('animate');
  };
  
  render() {
    return (
      <div>
        <div 
          ref="animatedElement"
          className="animated-box"
          style={{ 
            width: '100px', 
            height: '100px', 
            background: 'blue',
            transition: 'transform 0.3s ease'
          }}
        />
        <button onClick={this.startAnimation}>
          Start Animation
        </button>
      </div>
    );
  }
}

Mount/Unmount Utilities

/**
 * Unmount component from DOM node
 * @param {Element} container - DOM container element
 * @returns {boolean} True if component was unmounted
 */
function unmountComponentAtNode(container);

Usage Examples:

import { unmountComponentAtNode } from 'preact-compat';
// or
import { unmountComponentAtNode } from 'preact-compat/lib/ReactMount';

// Clean up component
const container = document.getElementById('app');
const wasUnmounted = unmountComponentAtNode(container);

if (wasUnmounted) {
  console.log('Component successfully unmounted');
} else {
  console.log('No component was mounted in container');
}

Performance Best Practices

import { PureComponent } from 'preact-compat';

// Use PureComponent for components with simple props
class OptimizedListItem extends PureComponent {
  render() {
    const { item, onSelect } = this.props;
    return (
      <div onClick={() => onSelect(item.id)}>
        {item.name}
      </div>
    );
  }
}

// Memoize expensive computations outside render
class ExpensiveComponent extends PureComponent {
  constructor(props) {
    super(props);
    this.memoizedResult = null;
    this.lastInput = null;
  }
  
  expensiveCalculation = (input) => {
    if (this.lastInput === input && this.memoizedResult !== null) {
      return this.memoizedResult;
    }
    
    // Simulate expensive calculation
    const result = input.split('').reverse().join('').repeat(1000);
    this.memoizedResult = result;
    this.lastInput = input;
    return result;
  };
  
  render() {
    const result = this.expensiveCalculation(this.props.input);
    return <div>{result.substring(0, 100)}...</div>;
  }
}

// Use keys for dynamic lists
class DynamicList extends Component {
  render() {
    return (
      <div>
        {this.props.items.map(item => (
          <OptimizedListItem 
            key={item.id}  // Important for performance
            item={item}
            onSelect={this.props.onSelect}
          />
        ))}
      </div>
    );
  }
}

Import Patterns

// Main imports
import { PureRenderMixin, ReactPerf } from 'preact-compat';

// Specific library imports  
import PureRenderMixin from 'preact-compat/lib/ReactComponentWithPureRenderMixin';
import ReactPerf from 'preact-compat/lib/ReactPerf';
import { addEndEventListener, removeEndEventListener } from 'preact-compat/lib/ReactTransitionEvents';
import { unmountComponentAtNode } from 'preact-compat/lib/ReactMount';

// CommonJS
const { PureRenderMixin, ReactPerf } = require('preact-compat');

Types

interface PureRenderMixinType {
  shouldComponentUpdate(nextProps: object, nextState: object): boolean;
}

interface ReactPerfType {
  start(): void;
  stop(): void;
  isRunning(): boolean;
  getLastMeasurements(): Array<any>;
  getExclusive(measurements: Array<any>): Array<any>;
  getInclusive(measurements: Array<any>): Array<any>;
  getWasted(measurements: Array<any>): Array<any>;
  getOperations(measurements: Array<any>): Array<any>;
  printExclusive(measurements: Array<any>): void;
  printInclusive(measurements: Array<any>): void;
  printWasted(measurements: Array<any>): void;
  printOperations(measurements: Array<any>): void;
}

type TransitionEventListener = (event: TransitionEvent | AnimationEvent) => void;

interface TransitionEventUtils {
  addEndEventListener(node: Element, eventListener: TransitionEventListener): void;
  removeEndEventListener(node: Element, eventListener: TransitionEventListener): void;
}

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