diff --git a/README.md b/README.md index cf43944..6ab3e0e 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,24 @@ export default track({ })(FooPage); ``` +### Usage with React Hooks + +Following the example above, once a component is wrapped with `track` we can access a `tracking` object via the `useTracking` hook from anywhere in the sub-tree: + +```js +import { useTracking } from 'react-tracking' + +const SomeChild = props => { + const tracking = useTracking() + +
{ + tracking.trackEvent({ action: 'click' }); + }} + /> +} +``` + This is also how you would use this module without `@decorators`, although this is obviously awkward and the decorator syntax is recommended. ### Custom `options.dispatch()` for tracking data diff --git a/package-lock.json b/package-lock.json index 68e7916..aaaa3a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3931,7 +3931,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -3952,12 +3953,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3972,17 +3975,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4099,7 +4105,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4111,6 +4118,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4125,6 +4133,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4132,12 +4141,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4156,6 +4167,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4236,7 +4248,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4248,6 +4261,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4333,7 +4347,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4369,6 +4384,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4388,6 +4404,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4431,12 +4448,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/package.json b/package.json index 8010ced..4cf7e18 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ }, "peerDependencies": { "core-js": "2.x", - "react": "^16.3", + "react": "^16.8", "prop-types": "^15.x" }, "devDependencies": { diff --git a/src/__tests__/e2e.test.js b/src/__tests__/e2e.test.js index dc59c0e..a5ef64e 100644 --- a/src/__tests__/e2e.test.js +++ b/src/__tests__/e2e.test.js @@ -1,5 +1,5 @@ /* eslint-disable react/destructuring-assignment,react/no-multi-comp,react/prop-types,react/prefer-stateless-function */ -import React from 'react'; +import React, { useContext } from 'react'; import { mount } from 'enzyme'; const dispatchTrackingEvent = jest.fn(); @@ -12,13 +12,13 @@ const testState = { booleanState: true }; describe('e2e', () => { // eslint-disable-next-line global-require - const track = require('../').default; + const { default: track, useTracking, ReactTrackingContext } = require('../'); beforeEach(() => { jest.clearAllMocks(); }); - it('defaults moslty everything', () => { + it('defaults mostly everything', () => { @track(null, { process: () => null }) class TestDefaults extends React.Component { render() { @@ -584,4 +584,60 @@ describe('e2e', () => { page: 'Page', }); }); + + it('root context items are accessible to children', () => { + const App = track()(() => { + return ; + }); + + const Child = () => { + const trackingContext = useContext(ReactTrackingContext); + expect(Object.keys(trackingContext.tracking)).toEqual([ + 'data', + 'dispatch', + 'process', + ]); + return
; + }; + + mount(); + }); + + it('dispatches tracking events from a useTracking hook tracking object', () => { + const outerTrackingData = { + page: 'Page', + }; + + const Page = track(outerTrackingData, { dispatch })(props => { + return props.children; + }); + + const Child = () => { + const tracking = useTracking(); + + expect(tracking.getTrackingData()).toEqual(outerTrackingData); + + return ( +