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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lonerooftop/kitt-data-react

v4.8.3

Published

This package includes the glue between `kitt-data`, `kitt-ui` and your React app. It contains a number of convenient hooks for authenticating and connecting to the API, as well as some wrapper components.

Readme

About

This package includes the glue between kitt-data, kitt-ui and your React app. It contains a number of convenient hooks for authenticating and connecting to the API, as well as some wrapper components.

Development

The development setup and dependencies are purposefully kept to the bare minimum. Notably, there's no Babel setup to transpile JSX into Javascript. Instead, components use React.createElement directly.

This package targets only greenfield browsers (Chrome, Edge, Firefox, Safari).

NOTE: for working with local kitt dependencies rather than the published NPM packages, you might need to manually run npm link @lonerooftop/kitt-ui and npm link @lonerooftop/kitt-data first.

Testing

We use Jest to write & run unit tests. Just run:

$ npm test

to execute the tests.

Open issues with testing:

When testing hooks and rendering the test components the assertion checks the initial value/state of the hooks. setTimeout is used to wrap the assertion in order to check the right result of the hook. This needs to be checked and fixed when the right solution is found.

Components

Fetch

A wrapper around useFetch. Use this when you don't want to handle error or loading state and just want to get the result back.

Props

  • loaderProps: transparently passes props to
  • See useFetch: method, query, transform, timeout, maxAge.

Returns

Fetch expects a function as child, which receives the fetch result.

Example

Simple query:

import { Fetch } from '@lonerooftop/kitt-data-react'

<Fetch method='getZones' query={{ filter_zones: 'metadata!=hide_bid' }}>
  {(result) => {
    console.log(result)
    return null
  }}
</Fetch>

Multiple queries:

import { Fetch } from '@lonerooftop/kitt-data-react'

<Fetch
	method='getZoneMetrics'
	query={[
		{ building_id: 'd3a259ba-72e2-4e0d-9968-d00bac604ba4', startdatetime: '2020-02-14T00:00:00.000+01:00', enddatetime: '2020-02-15T00:00:00.000+01:00' },
		{ building_id: 'd3a259ba-72e2-4e0d-9968-d00bac604ba4', startdatetime: '2020-02-15T00:00:00.000+01:00', enddatetime: '2020-02-16T00:00:00.000+01:00' },
	]}>
  {([ resultA, resultB ]) => {
    console.log(resultA, resultB)
    return null
  }}
</Fetch>

Subscribe

A wrapper around useSocket that will show loader or error fallbacks.

Props

See useSocket: method, query, etc.

Returns

Fetch expects a function as child, which receives the fetch result.

Example

import { Subscribe } from '@lonerooftop/kitt-data-react'

<Subscribe method='getLatestZoneMetric' query={{ building_id: 'd3a259ba-72e2-4e0d-9968-d00bac604ba4' }}>
  {({ state, connection, lastMessage }) => {
    // whenever the state or lastMesage changes, this will be called again
    console.log(state, connection, lastMessage)
    return null
  }}
</Fetch>

TimedLoader

A wrapper that will show a spinner with self-updating message the longer it renders.

Props

  • explanation: string|node, explanation text that will be shown
  • inline: bool, wether to show an or component

Userdata

To fetch and store data on behalf of the user, add this wrapper to your app. It's a React context provider that returns the following value:

  • error: error response from the server (e.g. when fetching or posting failed)
  • loading: boolean
  • preferences: JSON-parsed object. The JSON parsing is done by getUserData. This is to work around the fact that the server only accepts strings for each value.
  • update: a function that you send your changed keys & values to.

There are two props that you can pass to the provider:

  • maxAge: the duration in milliseconds that getUserData should be cached. You probably want to keep this value low (the default is 1 minute). This ensures that the whenever the user updates their preferences, we re-fetch a fresh copy of their preferences from the backend if the time between the last fetch was greater than maxAge.
  • initialPreferences: optional object that contains any default keys

If you use this provider, you also want to look at its companion hooks.

Sending new or updated data

Setting or changing data is done with the update function. Its only parameter is (a diff of) the data you want to send. Note that only simple key/value pairs are accepted by the API. To send arrays, have a look at the useUserdataList hook.

update({ foo: 'bar' })

It's recommended to send only new or updated keys, they will be merged with the existing ones.

useUserdata

Use this hook to get access to any of the above keys from the Userdata context provider.

const UserdataConsumer = () => {
  const { error, loading, preferences, update } = useUserdata()
  // do stuff
  return <div />
}
  • useUserdataList: this hook is to make it easier to work with arrays.
const UserdataListConsumer = () => {
  const { list, has, add, remove } = useUserdataList('favorites')

  return (
    <ul>
      {list.map(item =>
        <li key={item}>
          {item}

          <button onClick={() => remove(item)}>Delete</button>
        </li>
      )}
    </ul>
  )
}

Props

See useSocket: method, query, etc.

Returns

Fetch expects a function as child, which receives the fetch result.

Example

import { Subscribe } from '@lonerooftop/kitt-data-react'

<Subscribe method='getLatestZoneMetric' query={{ building_id: 'd3a259ba-72e2-4e0d-9968-d00bac604ba4' }}>
  {({ state, connection, lastMessage }) => {
    // whenever the state or lastMesage changes, this will be called again
    console.log(state, connection, lastMessage)
    return null
  }}
</Fetch>

Hooks

useFetch

A React hook that wraps around kitt-data's getFromPIE. Use this for fetching from any supported API v4 method. Unless you have complex query requirements (such as fetching from multiple different methods in parallel), this should be your go-to hook for all query needs.

Parameters:

Pass an object with the following keys:

  • method: string, a valid API method; see the API documentation. Required.
  • query: query parameters valid for this API method. Accepts object, string or an instance of URLSearchParams. Additionally, you can pass an array of queries; this will trigger multiple parallel fetches. Optional depending on the method.
  • transform: function that transforms the result (if successful). Optional, defaults to (data) => data.result.
  • timeout: number (milliseconds) after which the request will be aborted. Optional, no default.
  • maxAge: number (milliseconds) after which the cached response will be expired. Optional, defaults to 6 hours (6 * 60 * 60 * 1000).
  • isAbortable: boolean, set to "true" by default. It enables the aborting the fetch requests

Example:

import { useFetch, FETCH_STATES } from '@lonerooftop/kitt-data-react'

function FetchZones ({ children, ...options }) {
  let { error, result, state } = useFetch(options)

  if (options.debug) {
    console.debug({ error, result, state, ...options })
  }

  switch (state) {
    case FETCH_STATES.ERROR:
    case FETCH_STATES.ABORT:
      return React.createElement(ErrorMessage, { error })
    case FETCH_STATES.SUCCESS:
      return children(result)
    case FETCH_STATES.INITIAL:
    case FETCH_STATES.FETCHING:
      return React.createElement(TimedLoader, null)
    default:
      throw new Error('invalid state: ' + state)
  }
}

Abortable fetch:

In order to reduce the number of duplicate requests or to cancel the request when navigating to another page we added the isAbortable property to useFetch hook. It enables the creation of the AbortController instance and aborts the fetch request automatically if the user navigates to another page or if the previous request is in progress and user triggers the new request. By default the feature is set to true. We can easily disable it by setting the property to false in the app. The AbortController is set as a part of state in reducer and can be access from the app if we want it.

useSocket

A React hook that sets up a Websocket connection to API methods that support it. It will try to keep the connection alive (using reconnecting-websocket underneath).

Parameters

  • method: string, a valid API method; see the API documentation. Required.
  • query: query parameters valid for this API method. Accepts object, string or an instance of URLSearchParams. Additionally, you can pass an array of queries; this will trigger multiple parallel fetches. Optional depending on the method.
  • onOpen: function, callback that executes when the connection opens
  • onMessage: function, callback that executes when a new message arrives
  • onError: function, callback that executes when there's an error
  • onClosed: function, callback that executes when the connection closed

See https://github.com/pladaria/reconnecting-websocket:

  • maxReconnectionDelay?: number; // max delay in ms between reconnections
  • minReconnectionDelay?: number; // min delay in ms between reconnections
  • reconnectionDelayGrowFactor?: number; // how fast the reconnection delay grows
  • minUptime?: number; // min time in ms to consider connection as stable
  • connectionTimeout?: number; // retry connect if not connected after this time, in ms
  • maxRetries?: number; // maximum number of retries
  • maxEnqueuedMessages?: number; // maximum number of messages to buffer until reconnection
  • startClosed?: boolean; // start websocket in CLOSED state, call .reconnect() to connect
  • debug?: boolean; // enables debug output

Returns

  • state: string, the connection state, one of INITIAL, CONNECTING, OPEN, CLOSING or CLOSED
  • connection: direct reference to the Websocket connection object
  • lastMessage: the JSON-parsed result of the last message

Example

import { useSocket, WEBSOCKET_STATES } from '../hooks/useSocket'

export function useSocketHistory ({ children, ...options }) {
  let socket = useSocket(options)
  let [ log, updateLog ] = React.useState([])

  React.useEffect(() => {
    updateLog(log.concat(lastMessage))
  }, [ lastMessage ])

  return log
}