Skip to content

Latest commit

 

History

History
453 lines (282 loc) · 7.32 KB

DRAFT_README.md

File metadata and controls

453 lines (282 loc) · 7.32 KB

Slap

Scalable and performant architecture for large React application

  • TypeScript ready
  • Minimal boilerplate code
  • No additional wrappers for components
  • Scale your app with modules and Dependency Injection
  • Autogenerated setters and getters

Example 1

// Define a React component
function FormComponent() {
  
  // define a module
  const module = useModule(() => {

    // inject a reactive state
    const state = injectState({
      name: 'Alex',
      address: 'Earth'
    });
    
    function reset() {
      this.state.mutate(state => {
        state.name = '';
        state.address = '';
      })
    }

    // export state and method for component
    return { state, reset }
  });

  // select methods and state from the module
  const { name, setName, address, setAddress, reset } = module;
  
  // render TSX
  return (
    <div>
      <h1>Hello {name} from {address}</h1>
      Name <TextInput value={name} onChange={setName} />
      Address <TextInput value={address} onChange={setAddress} />
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Alternative way

// define a module
class UserModule {

  // inject a reactive state
  state = injectState({
    name: 'Alex',
    address: 'Earth',

    reset() {
      this.name = '';
      this.address = '';
    }
  });
  
};

// Define a React component
function FormComponent() {

  // select methods and state from the module
  const { bind, reset } = useModule(UserModule);

  // render TSX
  return (
    <div>
      <h1>Hello {name} from {address}</h1>
      Name <TextInput {...bind.name} />
      Address <TextInput {...bind.address }/>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Getting started with services

class ShopService {

  cartState = injectState({
    items: [],
    addItem(item: string) {
      this.cart.push(item);
    }
  });

  checkout() {
    alert(`Your items: ${this.cartState.items.join(',')}`);
    this.cartState.setItems([]);
  }

};

function ShopComponent() {

  const { itemsCount, addPopcorn, checkout } = useModule(() => {
    const shop = inject(ShopService);
    function addPopcorn() {
      shop.cartState.addItem('Popcorn');
    }
    return {
      addPopcorn,
      get itemsCount() {
        return shop.items.length;
      },
      checkout() {
        shop.checkout();
      }
    }
  });

  return (
    <div>
      <h1>You have {itemsCount} in your cart</h1>
      <button onClick={addPopcorn}>Add popcorn</button>
      <button onClick={checkout}>Checkout</button>
    </div>
  )
}

function MyApp() {
  const app = createApp({ ShopService });
  return <ReactModules app={app}><ShopComponent/></ReactModules>
}


Extend modules

class FooBarModule {
  foo = 1;
  bar = 2;
};

function MyComponent() {
  const { foo, bar, sum } = useModule(FooBarModule).extend(module => {
    sum: module.foo + module.bar;
  });

  // renders "1 + 2 = 3"
  return <>{foo} + {bar} = {fooPlulBar}</>
}

Modules composition

class FooModule {
  foo: 1;
};

class BarModule {
  bar: 2;
};

class FooBarModule {
  fooModule = injectChild(FooModule);
  barModule = injectChild(BarModule);
  get sum() {
    return this.fooModule.foo + this.barModule.bar;
  }
};