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

restash

v0.2.4

Published

Simple React context store, set it or get it.

Downloads

11

Readme

Restash is a simple React context store which uses useReducer behind the scenes. The API is broken into components so that you can either use the default implementation or build up your own.

NEW!!

Restash now supports dot notation for properties! The below will give you

// Consider this state
const state = {
  person: {
    firstName: 'Milton',
    lastName: 'Waddams',
    numbers: {
      home: '8985551212',
      mobile: '8985551234'
    }
  }
};

const [nestedState, setNestedState] = useStore('person.numbers.mobile');

// Nested state here will be equal to '8985551234';
// Update it as follows.

const updateState = (value) => {
  setNestedState(value);
};

Getting Started

$ npm install restash -s

OR

$ yarn add restash

Restash

It's best or most flexibile if you break up your setup in a few small parts. Exposing the Provider to wrap your application, a store or init file to configure your store and finally using the exposed hook.

Initialize Restash

After providing your context above initialize Restash in a file called for example restash.tsx for example. Then call createRestash passing our options and then export our new Restash store.

import { createRestash } from 'restash';

const initialState = {
  firstName: 'Milton',
  lastName: 'Waddams'
};

const { Provider, useStore } = createRestash({initialState});

export {
  Provider,
  useStore
}

Provide Context

Using our export from above expose the Provider and wrap our application so it knows about our context.

import { Provider } from './restash';

// NOTE: you can also provide the initialState and reducer
// as params to your provider if you wish. If you provide
// a reducer or inital state in your "createRestash" init
// options those will be favored over params here.

const App = () => {
  return (
    <Provider>
        // Your App Here
    </Provider>
  );  
}

Using Hook

We can now use our hook that's been created by our new Restash store.

import { useStore } from './restash';

const Home = () => {

  const [state, dispatch] = useStore();

  const changeState = (key) => {
    return (e) => {
      dispatch({ [key]: e.target.value });
    };
  };

  return (
    <div>
      <h2 style={{ marginBottom: '12px' }}>Use Store</h2>
      <hr style={{ marginBottom: '20px' }} />
      <p style={{ padding: '12px', backgroundColor: '#eee', width: '50%' }}>
        Simple example wiring up input elements to state values
        changing the state on blur of each field.
      </p>
      <div style={{ marginBottom: '12px' }}>
        First Name: <input type="text" onBlur={changeState('firstName')} defaultValue={state.firstName} />
      </div>
      <div style={{ marginBottom: '12px' }}>
        Last Name: <input type="text" onBlur={changeState('lastName')} defaultValue={state.lastName} />
      </div>
      <h3 style={{marginTop: '32px'}}>Current State</h3>
      <pre>
        {JSON.stringify(state, null, 2)}
      </pre>
    </div>
  );

};

Middleware, Persistence & Statuses

Initializing with middleware is very similar to Redux. You create your middleware then call a helper method called applyMiddleware then pass to your options. By default Restash supports thunks which are useful for async tasks.

Restash currently comes with only one middleware. That being a simple console logger. Redux middleware should work however in many cases.

import { createRestash, logger } from 'restash';

const initialState = {
  firstName: 'Milton',
  lastName: 'Waddams'
};

// The only logger options are that of styles
// for colorizing and styling in your console.
// see source for details.

const middleware = applyMiddleware(logger());

const options {

  // The initial data state.
  initialState,

  // The middleware to process before updating state.
  middleware,

  // This is required when using Restash in an SSR environment.
  // Your state will load from this key. If present Restash
  // will load it.
  ssrKey: 'some_unique_ssr_key',

  // this will cause state to persist within localStorage.
  // when your app loads it will again look for this key.
  persistent: 'some_unique_name' 

  // Statuses are used as the second dispatch argument.
  // The enable triggering things based on their state.
  statuses: ['start', 'progress', 'error', 'complete']

};

const { Provider, useStore } = createRestash(options);

export {
  Provider,
  useStore
}

Status

Restash includes a handy second arg on dispatch that allows you to set the status on dispatching an event. This is useful for updating your view based on this status. For example when making an async data requests.

NOTE: this examples assumes you have added statuses as shown above in our options in the previous section.

const Home = () => {

  // The third arg here is the restash store.
  // you can use this to get state, status 
  // you can also use this is middleware.
  const [state, dispatch, restash] = useStore();

  // Although we're not updating the state here
  // you could update it along with the status.
  // This can really be handy stepping through 
  // a stepper or remembering and updating a 
  // status filling out a form. Once you get
  // the hang of it, can be quite useful.
  const changeStatus = (e) => {
    dispatch(null, e.target.value);
  };

  return (
    <div>
     <h3 style={{ marginBottom: '12px' }}>Current Status</h3>
      <hr style={{ marginBottom: '20px' }} />
      <div style={{ color: '#fff', backgroundColor: 'darkblue', padding: '6px', display: 'inline' }}>
        <span>{(restash.status || '').toUpperCase()}</span> &nbsp;
        <select defaultValue={restash.status} onChange={changeStatus}>
          <option value="">Please Select</option>
          <option>mounted</option>
          <option>start</option>
          <option>progress</option>
          <option>error</option>
          <option>complete</option>
        </select>
      </div>
    </div>
  );

};

Server Side React (SSR)

To use Restash with server side react you'll need to expose your state to the window of the application. This is common practice with other libs such as Redux. Here's an example using Restash with NextJS.

First ensure you've enabled Restash for use with SSR. You can other pass true to use the default SSR key or pass your own string.

const { Provider, useStore } = createRestash({
  ssrKey: true // or your own key such as __APP_STATE__
});

Using the default SSR key or the one you provided expose that to a custom _document.jsx (or _docuemnt.tsx) page in your NextJS /pages directory.

const state = JSON.stringify({ some_initial_state });
<script dangerouslySetInnerHTML={{ __html: `window.${SSR_KEY} = ${state};` }} />

See Below for Complete Example

The Below example is for NextJS but you should be able to easily adapt to any SSR environemnt. The trick with SSR is to bind your state to a window prop as you see above and also below inside our script tag within the head element.


const SSR_KEY = '__APP_STATE__'; // or use default __RESTASH_APP_STATE__

class MyDocument extends Document {

  static async getInitialProps(ctx) {
    const { res } = ctx;
    const app = res && res.meta ? res.meta : {};
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps, app };
  }

  render() {

    const { app } = this.props;
    const state = JSON.stringify({ ...DEFAULTS, ...app });

    return (
      <Html>
        <Head />
        <script dangerouslySetInnerHTML={{ __html: `window.${SSR_KEY} = ${state};` }} />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }

}

export default MyDocument;

Docs

See https://blujedis.github.io/restash/

Change

See CHANGE.md

License

See LICENSE.md