Skip to content

darkobits/react-kit

Repository files navigation

Install

npm install --save @darkobits/react-kit

Use


render

// Import
import { render } from '@darkobits/react-kit/render';
// Signature
function render(selector: string, element: JSX.Element): () => void;

Shorthand for rendering a React root at the provided selector using react-dom/client. This function performs the following actions:

  1. Use document.querySelector to locate the target element indicated by selector.
  2. If no element was found, throw.
  3. Create a root using createRoot.
  4. Call root.render, passing the provided element.
  5. Return the root's unmount function.

⚠️ This package declares react-dom as a peer dependency. However, you should still install react-dom as a dependency of your project, even if your package manager automatically installs peer dependencies.

index.tsx

import { render } from '@darkobits/react-kit/render';
import { App } from './App';
render('#root', <App />);

lazy

// Import
import { lazy } from '@darkobits/react-kit/lazy';
// Signature
function lazy<
  M extends Record<string, any>,
  K extends keyof M
>(loader: () => Promise<M>): AsPreLoadableLazyExotics<M>

Facilitates the lazy loading of React components with some extras:

  • You can use destructuring to reference named exports.
  • You may optionally optimistically pre-load components.

Assuming we have a file Components.tsx that exports 2 React components and some other value:

Components.tsx

export const Foo = () => {
  return (
    <div>Foo</div>
  )
};

export const Bar = () => {
  return (
    <div>Bar</div>
  );
}

export const Baz = false;

Then, in another file, we can lazily import these components thusly:

App.tsx

import { lazy } from '@darkobits/react-kit/lazy';

// Foo, Bar are correctly typed as lazy React components with their typed props,
// if applicable.
const { Foo, Bar } = lazy(async () => import('./Components.tsx'));

// Type error; Baz is not a component.
const { Baz } = lazy(async () => import('./Components.tsx'));

export const App = () => {
  return (
    <Foo />
    <Bar />
  )
}

Pre-Loading

This function attaches a static preload method to components that can be invoked to optimistically pre-load a component. This method returns a Promise that will resolve when the component has loaded.

import { lazy } from '@darkobits/react-kit/lazy';

const { Foo } = lazy(async () => import('./Components.tsx'));
await Foo.preload();

Caveats

  • When using this (or other solutions) to circumvent the default export requirement, tree-shaking will not work on the imported module. In most cases, this should not be an issue.

assertIsBrowser

// Import
import { assertIsBrowser } from '@darkobits/react-kit/assert-is-browser';
// Signature
function assertIsBrowser(label?: string): void;

Ensures the current context is a browser environment. Throws an error otherwise. Useful for writing functions that interact with browser APIs.

export function reticulateSplines() {
  assertIsBrowser();
  // Safely interact with window, document, etc.
}

This function accepts an optional argument, label, that will be used as a prefix in the error message should the function throw:

export function reticulateSplines() {
  assertIsBrowser('reticulateSplines');
  // Safely interact with window, document, etc.
}

This will throw errors with the message: [reticulateSplines] Not in a browser environment.


setCssVariable

// Import
import { setCssVariable } from '@darkobits/react-kit/css-variable';
// Signature
function setCssVariable(varName: string, value: any, scope = ':root'): void;

Sets a CSS variable on all elements matching the provided scope. The default scope is :root, which is equivalent to the html element.

// Set on <html>, available globally.
setCssVariable('--color', 'rgba(128, 128, 128, 0.6)');

// Only set on element(s) matching the provided selector.
setCssVariable('--color', 'rgba(128, 128, 128, 0.6)', '.my-element');

// To unset a variable, pass `false`, `null`, or `undefined`:
setCssVariable('--color', false);
setCssVariable('--color', null);
setCssVariable('--color');

hideCursor / showCursor

// Import
import { hideCursor, showCursor } from '@darkobits/react-kit/hide-cursor';
// Signatures
function hideCursor(): void;
function showCursor(): void;

Hides the cursor by adding a <style> tag to the <head> that sets the cursor to an image of a 1px by 1px transparent PNG. The cursor may be shown again by calling showCursor, which removes the <style> tag.

// To hide the cursor:
hideCursor();

// To show the cursor again:
showCursor();

emit

// Import
import { emit } from '@darkobits/react-kit/emit';
// Signature
function emit(eventName: string, eventData?: any): void;

Emits a CustomEvent on the window with optional event data. Event data will be assigned to the detail property of the CustomEvent.

Type-Safe Events

To add type-safety to this function as well as window.addEventListener and window.dispatchEvent, create a file with the .d.ts extension (globals.d.ts is common) in your project with the following:

interface WindowEventMap {
  'custom-event': CustomEvent<{
    kittens: true
  }>;
}

The interface WindowEventMap is what addEventListener and dispatchEvent use to look-up known event names and their corresponding data. The definition above will be merged with the global definition such that window.addEventListener will now be aware of custom-event and its event data.


injectScript

// Import
import { injectScript } from '@darkobits/react-kit/inject-script';
// Signature
function injectScript(src: string, attrs?: OptionalAttributes): Promise<void>

Facilitates loading external scripts at runtime by injecting a <script> tag into the <head>. Returns a Promise that resolves when the script has finished loading. By default, the script's type is set to text/javascript and its async flag is set to true. An optional second argument may be provided to override these settings and set additional attributes.

await injectScript('https://code.jquery.com/jquery-3.3.1.min.js');

await injectScript('https://code.jquery.com/jquery-3.3.1.min.js', {
  integrity: 'sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT',
  crossOrigin: 'anonymous'
});

jsonToBase64 / base64ToJson

// Import
import { jsonToBase64, base64ToJson } from '@darkobits/react-kit/json-base64';
// Signatures
function jsonToBase64(value: any): string;
function base64ToJson(value: string): any;

jsonToBase64 serializes the provided JSON value as a base-64-encoded string. base64ToJson deserializes a similarly-encoded value.

jsonToBase64({ kittens: true }) //=> 'eyJraXR0ZW5zIjp0cnVlfQ=='
base64ToJson('eyJraXR0ZW5zIjp0cnVlfQ==') //=> { kittens: true }

getPlatformDetails

// Import
import { getPlatformDetails } from '@darkobits/react-kit/platform';
// Signature
function getPlatformDetails(): Bowser.Parser.ParsedResult;

Returns details about the current browser, operating system, device, and rendering engine using bowser. This function creates a bowser parser, parses the current user agent string, then caches and returns the result. Subsequent invocations return the cached result.

Example result:

{
  browser: {
    name: 'Internet Explorer'
    version: '11.0'
  },
  os: {
    name: 'Windows'
    version: 'NT 6.3'
    versionName: '8.1'
  },
  platform: {
    type: 'desktop'
  },
  engine: {
    name: 'Trident'
    version: '7.0'
  }
}

isMobile

// Import
import { isMobile } from '@darkobits/react-kit/platform';
// Signature
function isMobile(): boolean;

Calls getPlatformDetails (see above) and returns true if the platform type is either mobile or tablet.


isStandalone

// Import
import { isStandalone } from '@darkobits/react-kit/platform';
// Signature
function isStandalone(): boolean;

Returns true if the page is currently being displayed in standalone mode, relevant for Progressive Web Apps.


prefetchImage

// Import
import { prefetchImage } from '@darkobits/react-kit/prefetch-image';
// Signature
function prefetchImage(imgUrl?: string): Promise<string>;

Pre-fetches an image by creating a new Image. Returns a promise that resolves with the provided URL when the image has finished loading. Useful for avoiding flicker / loading when adding images to the DOM dynamically.

If this function is provided a falsy value, it will resolve with an empty string.

⚠️ This function is memoized; subsequent invocations using the same URL will return the first value.

getImageUrlSomehow()
  .then(prefetchImage)
  .then(doSomethingWithImageUrl);

Other Resources

  • react-use - Comprehensive set of React hooks.

About

⚙️ Miscellaneous utilities for React applications.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published