Skip to content

Commit

Permalink
Merge pull request #20 from nytm/dispatchonmount-function
Browse files Browse the repository at this point in the history
dispatchOnMount as a function
  • Loading branch information
aneudy1702 authored Feb 15, 2017
2 parents 00ff78e + e85e6e2 commit cb0fe9a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 14 deletions.
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
## Installation

```
npm install --save nytm/nyt-react-tracking#v2.0.0
npm install --save nytm/nyt-react-tracking#v2.1.0
```

(Or whatever is [latest](https://github.com/nytm/nyt-react-tracking/releases), it was 2.0.0 as of this writing)
(Or whatever is the [latest version](https://github.com/nytm/nyt-react-tracking/releases))

## Usage
@track() expects two arguments, `trackingData` and `options`.
`@track()` expects two arguments, `trackingData` and `options`.
- `trackingData` represents the data to be tracked
- `options` is an optional object that accepts two properties:
- `dispatch`, which is a function to use instead of the default CustomEvent dispatch behavior. See the section on custom `dispatch()` later in this document.
- `dispatchOnMount`, when set to `true`, dispatches the tracking data when the component mounts to the DOM.
- `dispatchOnMount`, when set to `true`, dispatches the tracking data when the component mounts to the DOM. When provided as a function will be called on componentDidMount with all of the tracking context data as the only argument.

`nyt-react-tracking` is best used as a `@decorator()` using the [babel decorators plugin](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy).

Expand Down Expand Up @@ -94,9 +94,11 @@ NOTE: It is recommended to do this on some top-level component so that you only

### When to use `options.dispatchOnMount`

To dispatch tracking data when a component mounts, you can pass in `{ dispatchOnMount: true }` as the second parameter to `@track()`. This is useful for dispatching tracking data on "Page" components, for example.
You can pass in a second parameter to `@track`, `options.dispatchOnMount`. There are two valid types for this, as a boolean or as a function. The use of the two is explained in the next sections:

#### Using `options.dispatchOnMount` as a boolean

For example:
To dispatch tracking data when a component mounts, you can pass in `{ dispatchOnMount: true }` as the second parameter to `@track()`. This is useful for dispatching tracking data on "Page" components, for example.

```js
@track({ page: 'FooPage' }, { dispatchOnMount: true })
Expand All @@ -115,6 +117,23 @@ Of course, you could have achieved this same behavior by just decorating the `co

_Note: this is only in affect when decorating a Class or stateless functional component. It is not necessary when decorating class methods since any invocations of those methods will immediately dispatch the tracking data, as expected._

#### Using `options.dispatchOnMount` as a function

If you pass in a function, the function will be called with all of the tracking data from the app's context when the component mounts. The return value of this function will be dispatched in `componentDidMount()`. You do not have to use the app's context data, so you can explicitly define the entire shape of the tracking data to dispatch for a "page view" event, for example.

```js
@track({ page: 'FooPage' }, { dispatchOnMount: (contextData) => ({ event: 'pageDataReady' }) })
class FooPage extends Component { ... }
```

Will dispatch the following data (notice, the `contextData` was ignored in the function we defined):

```
{
event: 'pageDataReady'
}
```

### Advanced Usage

You can also pass a function as an argument instead of an object literal, which allows for some advanced usage scenarios such as when your tracking data is a function of some runtime values, like so:
Expand Down
10 changes: 8 additions & 2 deletions build/withTrackingComponentDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ function withTrackingComponentDecorator() {
args[_key] = arguments[_key];
}

return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref2 = WithTracking.__proto__ || (0, _getPrototypeOf2.default)(WithTracking)).call.apply(_ref2, [this].concat(args))), _this), _this.trackEvent = function (data) {
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref2 = WithTracking.__proto__ || (0, _getPrototypeOf2.default)(WithTracking)).call.apply(_ref2, [this].concat(args))), _this), _this.getTrackingData = function (data) {
return (0, _lodash2.default)({}, _this.getChildContext().tracking.data, data);
}, _this.trackEvent = function (data) {
_this.getTrackingDispatcher()(
// deep-merge tracking data from context and tracking data passed in here
(0, _lodash2.default)({}, _this.getChildContext().tracking.data, data));
_this.getTrackingData(data));
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
}

Expand Down Expand Up @@ -110,6 +112,10 @@ function withTrackingComponentDecorator() {
if (dispatchOnMount === true) {
this.trackEvent();
}

if (typeof dispatchOnMount === 'function') {
this.getTrackingDispatcher()(dispatchOnMount(this.getTrackingData()));
}
}
}, {
key: 'render',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nyt-react-tracking",
"version": "2.0.0",
"version": "2.1.0",
"description": "Declarative tracking for React apps.",
"author": "The New York Times",
"contributors": [
Expand Down
15 changes: 15 additions & 0 deletions src/__tests__/e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,19 @@ describe('e2e', () => {
},
});
});

it('will call dispatchOnMount as a function', () => {
const testDispatchOnMount = { test: true };
const dispatchOnMount = jest.fn(() => ({ dom: true }));

@track(testDispatchOnMount, { dispatch, dispatchOnMount })
class TestComponent extends React.Component {
render() { return null; }
}

mount(<TestComponent />);

expect(dispatchOnMount).toHaveBeenCalledWith(testDispatchOnMount);
expect(dispatch).toHaveBeenCalledWith({ dom: true });
});
});
12 changes: 7 additions & 5 deletions src/withTrackingComponentDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ export default function withTrackingComponentDecorator(
tracking: TrackingPropType,
};

getTrackingData = data => merge({}, this.getChildContext().tracking.data, data)

trackEvent = (data) => {
this.getTrackingDispatcher()(
// deep-merge tracking data from context and tracking data passed in here
merge(
{},
this.getChildContext().tracking.data,
data
)
this.getTrackingData(data)
);
}

Expand All @@ -57,6 +55,10 @@ export default function withTrackingComponentDecorator(
if (dispatchOnMount === true) {
this.trackEvent();
}

if (typeof dispatchOnMount === 'function') {
this.getTrackingDispatcher()(dispatchOnMount(this.getTrackingData()));
}
}

render() {
Expand Down

0 comments on commit cb0fe9a

Please sign in to comment.