react-spy
TypeScript icon, indicating that this package has built-in type declarations

0.12.0 • Public • Published

React Spy

A set of utilities for collecting UX-analytics of your React-application (ex: clicks, shows, errors and etc.)

npm i --save react-spy

Features

  • Easy integration with any ui-library (ex: Ant-Design)
  • Full control over the events

API


Usage

For example with Google Analytics

// Btn.js
import {spy} from 'react-spy';
 
const Btn = ({name, value}) => (<button name={name}>{value}</button>);
export default spy({
    id: ({name}) => name, // Computed `id` on based component properties
    listen: ['click'],    // DOM-events list
})(Btn);
 
 
// LoginForm.js
import {spy} from 'react-spy';
 
class LoginForm extends React.Component {
    // ...
    handleSubmit(evt) {
        evt.preventDefault();
        try {
            await api.login(this.getFormData());
            spy.send(this, 'success');
        } catch (err) {
            spy.send(this, 'failed', err);
        }
    }
 
    render() {
        return (
            <form onSubmit={this.handleEvent}>
                {/* ... */}
                <Btn name="login" value="Sign In"/>
                <Btn name="forgot" value="Forgot password"/>
            </form>
        );
    }
}
 
export default spy({
    id: "login-form",
    host: true,
    listen: ['mount', 'unmount'],
})(LoginForm);
 
 
// boot.js
import {addSpyObserver, addSpyErrorObserver} from 'react-spy';
 
addSpyObserver(chain => {
    // Send to GA
    ga('send', {
        hitType: 'event',
        eventCategory: chain[0], // ex: "login-form"
        eventAction: chain.slice(1).join('_'), // ex: "forgot_click"
    });
});
 
// Component Errors
addSpyErrorObserver(({error}) => {
    ga('send', 'exception', {
        exDescription: error.message,
        exFatal: false,
    });
});
 
ReactDOM.render(<App/>, document.body);

spy<Props>(options)

Decorate the component to collect analytics

  • options
    • id: string | (props, context?) => string — default @see propName description
    • propName: string — prop-name for id, by default spyId
    • listen: string[] — DOM-events to listen + error, mount and unmount
    • callbacks — list of observed callbacks that are passed to it via props
    • propName: string — name of the property responsible for the spy's id, by defaultspyId
    • host: boolean
import {spy} from 'react-spy';
 
export default spy({
    id: ({name}) => name,
    listen: ['click'],
})(function Btn({value}) {
    return <button>{value}</button>;
})
 
// Somewhere in the code
<Btn
    name="login"
    value="Sign in"
/>
// *click* -> ["login", "click"]

spy.send(cmp: React.Component, chain: string | string [], detail?: object): void

Send stats from the component and not only

  • cmp: React.Component — instance of React.Component
  • chain: string | string[] — name of metric
  • detail: object
import {spy} from 'react-spy';
 
export default spy({id: 'parent'})(class Box extends React.Component {
    render() {
        return (
            <button onClick={() => {spy.send(this, 'foo');}}>First</button>
            <button onClick={() => {spy.send(this, ['bar', 'baz'], {val: 123});}}>Second</button>
        );
    }
});
 
// Somewhere in a code
//   click on <First>:
//     - ["parent", "foo"] {}
//   click on <Second>:
//     - ["parent", "bar", "baz"] {val: 123}
//
// Somewhere in an another place:
//    spy.send(['global', 'label'], {time: 321}):
//      - ["global", "label"] {time: 321}

spy.error(cmp: React.Component, chain: string | string [], error: Error): void

send an error from the component and not only

  • cmp: React.Component — instance of React.Component
  • chain: string | string[] — name of metric
  • error: Error — any an error

addSpyObserver(fn: (chain: string[], detail: object) => void): UnsubsriberFn

Add observer of events for sending to the accounting system of analytics

import {addSpyObserver} from 'react-spy';
 
const unsubscribe = addSpyObserver(chain => {
    // Send to GA
    ga('send', {
        hitType: 'event',
        eventCategory: chain[0], // ex: "login-form"
        eventAction: chain.slice(1).join('_'), // ex: "forgot_click"
    });
});
 
// Somewhere (if you need to)
unsubscribe();

addSpyErrorObserver(fn: (detail: ErrorDetail) => void): UnsubsriberFn

Add observer of component errors

  • detail
    • error: Error — JavaScript error
    • info: object — React error info
    • chain string[] — spy id chain
import {addSpyErrorObserver} from 'react-spy';
 
addSpyErrorObserver(({error, chain}) => {
    // Send to GA
    ga('send', 'exception', {
        exDescription: error.message,
        exFatal: false,
    });
 
    // For dev
    console.error('[react-spy]', chain.join(' -> '));
    console.error(error);
});

intercept(rules: InterceptRules)

Intercepting a chain of events

import {intercept, UNCAUGHT} from 'react-spy';
 
intercept({
    'login-form': {
        // Interception of all chains, ex:
        //  - ["login-form", "forgot", "mount"]
        //  - ["login-form", "forgot", "click"]
        //  - etc
        'forgot'(send, chain, detail) {
            send(chain.concat('additional-id'));
        },
 
        // Processing of non-intercepted chains, ex:
        //  - ["login-form", "login", "click"]
        [UNCAUGHT](send, chain) {
            send(chain.concat('UNCAUGHT'));
            return false; // continue;
        }
    },
});

<Spy>...</Spy>

import {Spy} from 'react-spy';
 
const SomeFragment = ({condition, onShowDetail}) => (
    <div>
        <Spy id="top">
            <Button name="detail" value="Show detail" onClick={onShowDetail}/>
        </Spy>
 
        {condition &&
            <Spy id="bottom" listen={['mount', 'unmount'}>
                Detail
            </Spy>
        }
    </div>
);
 
// 1. *click on button* -> ["top", "detail", "click"]
// 2. *mounting* -> ["bottom", "mount"]

<SpyStep name="..."/>

The hidden spy element for steps monitoring

  • name: string — a step name
  • enter: string | string[] — the enter phase (optional)
  • leave: string | string[] — the leave phase (optional)

broadcast(chain: string[], detail?: object)

import {broadcast} from 'react-spy';
 
broadcast(['custom', 'event', 'chain'], {value: 'Wow'});
// or just
//   spy.send(['custom', 'event', 'chain'], {value: 'Wow'})

broadcastError(detail: ErrorDetail)

  • detail
    • error: Error — JavaScript error
    • chain string[] — spy id chain
    • info: object — React error info (optional)
import {broadcastError} from 'react-spy';
 
broadcastError({
    chain: ['login', 'submit', 'failed'],
    error: new Error('Internal Error'),
});
// or just
//   spy.error('localStorage', new Error('Read'));
//   spy.error(thisReactCmp, 'localStorage', new Error('save'));

Development

Readme

Keywords

none

Package Sidebar

Install

npm i react-spy

Weekly Downloads

3

Version

0.12.0

License

MIT

Unpacked Size

53.8 kB

Total Files

24

Last publish

Collaborators

  • rubaxa