npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

session-controller

v2.0.1

Published

**Session Controller** is an entry point for your React application, it: - provides application state storage - re-renders app on state updates - provides sensible way of splitting multi-page applications into asynchronously loaded modules

Downloads

5

Readme

Session Controller is an entry point for your React application, it:

  • provides application state storage
  • re-renders app on state updates
  • provides sensible way of splitting multi-page applications into asynchronously loaded modules

How does it work?

There are two classes in the module: Controller and Session:

  • Controller passes business logic and application state data to page components. It helps to group common actions and UI components, and load them asynchronously from a separate chunk (if Webpack is used). One Controller per application page should be fine.
  • Session provides state storage and a method to change currently active controller. Session also re-renders page when state is updated.

Session constructor takes two arguments: mount-point for React and a list of controllers. For example:

import { Session } from 'session-controller';
import ControllerB from './ControllerB';

const controllers = {
  ControllerA: () => import('./ControllerA'),
  ControllerB: () => { return Promise.resolve({ default: ControllerB }) };
}

const session = new Session(document.getElementById('mount-point'), controllers);

Note that for controllers object:

  • each value is a function that returns a Promise, that resolves a module
    • It will be either a () => import('./ControllerA') that creates a new async chunk.
    • or () => { return Promise.resolve({ default: ControllerB }) }, where ControllerB was previously imported
  • resolved modules default export should be a class. that's why ControllerB value resolves { default: ControllerB } value. It also has to conform to provided Controller interface
  • every key should be the same as resolved controller's value returned by name getter

Session constructor creates a store and subscribes to its updates to re-render current controller's view.

To change currently active application page, call session.mountController(controllerName: String) - this function will try to import controller from controllers object. E.g. session.mountController('ControllerA') will try to import ControllerA and render it's view property on success.

Re-render attempts caused by state changes made during controller mount period will be ignored.

Session will try to mountController('ErrorController', { error }) in case of import failure. If no ErrorController is found, an error will be thrown. ErrorController should not be loaded asynchronously.

All controllers are expected to:

  • be constructed with two arguments constructor(context: Object). context is session's property, that provides store and mountController references. payload is extra data that can be used to construct initial application state necessary to render controller's view.
  • have view property, that is going to be React root component while controller is active
  • have controllerWillMount(payload: Object) method. Usually payload is used to construct initial application state. This method is also called when mountController tries to set already active controller (note that session.controller.name getter is used to check that).
  • have dispose() method. This method is called when another controller is going to be mounted.

A sample controller might look like this:

class ExampleController extends Controller {
  constructor(context) {
    super(context);
    this.view = () => {
      return <div>Hello world!</div>;
    };
  }
  get name() {
    return 'ExampleController'
  }
  controllerWillMount() {}
  dispose() {}
}

This example doesn't show how to pass application state to controller's view.

To pass state to components you might want to use dependency injection. E.g. components-di module:

import { injectDeps } from 'components-di';

const actions = {
  helloWorld: (context) => { console.log('hello world')! }
}

const view = () => {
  return <div>Hello world!</div>;
};

class ExampleController extends Controller {
  constructor(context) {
    super(context);
    this.view = injectDeps(context, actions)(view);
  }
  reset() {}
  dispose() {}
}

In this case view's child components will be able to use provided context and actions via components-di useDeps method.

It also might be a good idea to extend Session, instead of using it directly (edited excerpt from live project, that uses session-controller):

import { Session } from 'session-controller';
import request from 'superagent';
import routingService from 'services/RoutingService'; // listens to browser history changes

class SessionController extends Session {
  constructor(mountPoint, controllers) {
    super(mountPoint, controllers);

    Object.assign(this.context, { config: { foo: 'bar' } });

    routingService.add('home', '/', ({ query }) => {
      request.get('/api/home').end((err, res) => {
        if (!err && res.ok) {
          this.mountController('HomeController', { data: res.body, query });
        } else {
          this.mountController('ErrorController', { error: err });
        }
      })
    })
  }
}

API

Controller:

  • constructor(context: Object)
  • controllerWillMount([payload: Object])
  • dispose()
  • get name()
  • view - React component

Session:

  • constructor(mountPoint: Node, controllers: Object)
  • mountController(controllerName: String)