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

immutability-helpers.mddocs/

Immutability Helpers

Data update utilities for managing immutable state transformations safely and efficiently.

Capabilities

Update Function

Immutable update utility based on MongoDB's query language for safe state modifications.

/**
 * Immutably update nested data structures
 * @param {any} object - Object to update
 * @param {UpdateSpec} spec - Update specification
 * @returns {any} New object with updates applied
 */
function update(object, spec);

/**
 * Update specification object
 */
interface UpdateSpec {
  /** Set a value */
  $set?: any;
  
  /** Merge an object (shallow merge) */
  $merge?: object;
  
  /** Push items to end of array */
  $push?: Array<any>;
  
  /** Add items to beginning of array */
  $unshift?: Array<any>;
  
  /** Splice array (remove/insert items) */
  $splice?: Array<[number, number, ...any[]]>;
  
  /** Apply function to transform value */
  $apply?: (value: any) => any;
  
  /** Toggle boolean value */
  $toggle?: Array<string>;
  
  /** Remove items from array by index */
  $unset?: Array<string | number>;
  
  /** Nested updates - any key can contain another UpdateSpec */
  [key: string]: UpdateSpec | any;
}

Usage Examples:

import update from 'preact-compat/lib/update';

// Initial state
const state = {
  user: {
    name: 'John',
    profile: {
      age: 30,
      preferences: ['music', 'sports']
    }
  },
  items: [1, 2, 3],
  settings: {
    theme: 'light',
    notifications: true
  }
};

// Update nested object
const newState1 = update(state, {
  user: {
    name: { $set: 'Jane' },
    profile: {
      age: { $set: 31 },
      preferences: { $push: ['reading'] }
    }
  }
});

// Merge objects
const newState2 = update(state, {
  settings: { $merge: { theme: 'dark', language: 'en' } }
});

// Array operations
const newState3 = update(state, {
  items: { $splice: [[1, 1, 10, 11]] } // Remove 1 item at index 1, insert 10, 11
});

// Apply function transformation
const newState4 = update(state, {
  user: {
    profile: {
      age: { $apply: age => age + 1 }
    }
  }
});

Common Update Patterns

import update from 'preact-compat/lib/update';

class TodoApp extends Component {
  state = {
    todos: [
      { id: 1, text: 'Learn React', completed: false },
      { id: 2, text: 'Build app', completed: false }
    ],
    filter: 'all'
  };
  
  // Add new todo
  addTodo = (text) => {
    const newTodo = {
      id: Date.now(),
      text,
      completed: false
    };
    
    this.setState(update(this.state, {
      todos: { $push: [newTodo] }
    }));
  };
  
  // Toggle todo completion
  toggleTodo = (id) => {
    const todoIndex = this.state.todos.findIndex(todo => todo.id === id);
    
    this.setState(update(this.state, {
      todos: {
        [todoIndex]: {
          completed: { $apply: completed => !completed }
        }
      }
    }));
  };
  
  // Remove todo
  removeTodo = (id) => {
    const todoIndex = this.state.todos.findIndex(todo => todo.id === id);
    
    this.setState(update(this.state, {
      todos: { $splice: [[todoIndex, 1]] }
    }));
  };
  
  // Update filter
  setFilter = (filter) => {
    this.setState(update(this.state, {
      filter: { $set: filter }
    }));
  };
  
  // Bulk operations
  completeAll = () => {
    this.setState(update(this.state, {
      todos: { $apply: todos => 
        todos.map(todo => ({ ...todo, completed: true }))
      }
    }));
  };
  
  render() {
    const { todos, filter } = this.state;
    
    return (
      <div>
        <input 
          onKeyPress={(e) => {
            if (e.key === 'Enter') {
              this.addTodo(e.target.value);
              e.target.value = '';
            }
          }}
          placeholder="Add todo..."
        />
        <button onClick={this.completeAll}>Complete All</button>
        
        {todos.map(todo => (
          <div key={todo.id}>
            <input 
              type="checkbox"
              checked={todo.completed}
              onChange={() => this.toggleTodo(todo.id)}
            />
            <span style={{ 
              textDecoration: todo.completed ? 'line-through' : 'none' 
            }}>
              {todo.text}
            </span>
            <button onClick={() => this.removeTodo(todo.id)}>Remove</button>
          </div>
        ))}
      </div>
    );
  }
}

Advanced Update Patterns

import update from 'preact-compat/lib/update';

// Complex nested updates
const complexState = {
  users: {
    byId: {
      1: { name: 'John', posts: [10, 20] },
      2: { name: 'Jane', posts: [30] }
    },
    allIds: [1, 2]
  },
  posts: {
    byId: {
      10: { title: 'Post 1', likes: 5 },
      20: { title: 'Post 2', likes: 3 },
      30: { title: 'Post 3', likes: 8 }
    },
    allIds: [10, 20, 30]
  }
};

// Add new user with post
function addUserWithPost(state, user, post) {
  return update(state, {
    users: {
      byId: { $merge: { [user.id]: user } },
      allIds: { $push: [user.id] }
    },
    posts: {
      byId: { $merge: { [post.id]: post } },
      allIds: { $push: [post.id] }
    }
  });
}

// Update multiple related entities
function likePost(state, postId, userId) {
  return update(state, {
    posts: {
      byId: {
        [postId]: {
          likes: { $apply: likes => likes + 1 }
        }
      }
    },
    users: {
      byId: {
        [userId]: {
          likedPosts: { $push: [postId] }
        }
      }
    }
  });
}

// Conditional updates
function updateUserIfExists(state, userId, updates) {
  if (state.users.byId[userId]) {
    return update(state, {
      users: {
        byId: {
          [userId]: { $merge: updates }
        }
      }
    });
  }
  return state;
}

Import Patterns

// Main import
import update from 'preact-compat/lib/update';

// CommonJS
const update = require('preact-compat/lib/update');

Types

interface UpdateSpec {
  $set?: any;
  $merge?: object;
  $push?: Array<any>;
  $unshift?: Array<any>;
  $splice?: Array<SpliceOperation>;
  $apply?: (value: any) => any;
  $toggle?: Array<string>;
  $unset?: Array<string | number>;
  [key: string]: UpdateSpec | any;
}

type SpliceOperation = [number, number, ...any[]];

type UpdateFunction = <T>(object: T, spec: UpdateSpec) => T;

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