vwf .

Production Patterns

Production-ready patterns with live, editable code examples

Dynamic List Management

State

Add, remove, and update items in a reactive list

// Working with arrays and objects in state
const items = van.state(['Apple', 'Banana', 'Orange']);
const newItem = van.state('');
const filter = van.state('');

const addItem = () => {
  if (newItem.val.trim()) {
    // Create new array to trigger reactivity
    items.val = [...items.val, newItem.val.trim()];
    newItem.val = '';
  }
};

const removeItem = (index) => {
  // Filter creates new array, triggering update
  items.val = items.val.filter((_, i) => i !== index);
};

const clearAll = () => {
  items.val = [];
};

// Derived filtered items
const filteredItems = () => {
  const searchTerm = filter.val.toLowerCase();
  return searchTerm ?
    items.val.filter(item => item.toLowerCase().includes(searchTerm)) :
    items.val;
};

return div(
  { class: 'space-y-4 p-4' },
  h3({ class: 'text-lg font-semibold text-midnight' }, 'Arrays in State'),

  // Add item form
  div({ class: 'flex gap-2' },
    input({
      type: 'text',
      placeholder: 'Add new item...',
      class: 'flex-1 px-3 py-2 border border-mist rounded-lg',
      value: newItem,
      oninput: (e) => newItem.val = e.target.value,
      onkeypress: (e) => e.key === 'Enter' && addItem()
    }),
    Button({
      class: 'vwfcolor-sky solid vwfsize-md',
      onclick: addItem
    }, 'Add Item'),
    Button({
      class: 'vwfcolor-sunset outerline vwfsize-md',
      onclick: clearAll,
      disabled: () => items.val.length === 0
    }, 'Clear All')
  ),

  // Filter input
  input({
    type: 'text',
    placeholder: 'Filter items...',
    class: 'w-full px-3 py-2 border border-mist rounded-lg',
    value: filter,
    oninput: (e) => filter.val = e.target.value
  }),

  // Display stats
  div({ class: 'flex gap-4 text-sm text-smoke' },
    span('Total items: ', () => items.val.length),
    span('Filtered: ', () => filteredItems().length)
  ),

  // Reactive list rendering with filtered items
  div({ class: 'space-y-2' },
    () => filteredItems().length > 0 ?
      div({ class: 'space-y-2' },
        ...filteredItems().map((item, index) =>
          div({ class: 'flex items-center justify-between p-3 bg-white rounded-lg shadow-sm border border-mist' },
            span({ class: 'font-medium' }, item),
            Button({
              class: 'vwfcolor-sunset ghost vwfsize-sm',
              onclick: () => removeItem(items.val.indexOf(item))
            }, '✕')
          )
        )
      ) :
      div({ class: 'text-center text-smoke py-8' },
        filter.val ? 'No items match your filter' : 'No items yet. Add one above!'
      )
  )
);

▶️ Live Preview

Arrays in State

Total items: 3Filtered: 3
Apple
Banana
Orange

💡 Click "Edit Code" to modify the example

🔄 Click "Apply Changes" to see your modifications

↩️ Click "Reset" to restore original code

📋 Best Practices

State Management

• Use individual van.state() for each value

• Keep state close to where it's used

• Update arrays immutably with spread operator

• Use arrow functions for reactive values

Performance

• Debounce expensive operations

• Use keys for list items

• Avoid complex computations in render

• Clean up timers and listeners

Component Design

• Accept both props and children

• Use parseArgs for flexibility

• Provide sensible defaults

• Keep components focused

User Experience

• Show loading states

• Provide immediate feedback

• Handle errors gracefully

• Add smooth transitions