React Hooks - state and lifecycle methods without a class (React 16.7.0-alpha)

I tried to see what a useTracker hook might look like, and it seems the following code is pretty close (including a drop-in reimplementation of react-meteor-data’s withTracker HOC on top of it)

import React, { memo, useState, useEffect, useCallback } from 'react';
import { Tracker } from 'meteor/tracker';

export function useTracker(reactiveFn, dependencies) {
  const [trackerData, setTrackerData] = useState(null);
  const callback = useCallback(reactiveFn, dependencies);

  useEffect(() => {
    let computation;
    Tracker.nonreactive(() => {
      computation = Tracker.autorun(() => setTrackerData(callback()));
    });
    return () => computation.stop();
  }, [callback]);

  return trackerData;
}

export const withTracker = options => Component => {
  const expandedOptions = typeof options === 'function' ? { getMeteorData: options } : options;
  const { getMeteorData, pure = true } = expandedOptions;

  function WithTracker(props) {
    const data = useTracker(() => getMeteorData(props) || {}, [props]);
    return data ? <Component {...{ ...props, ...data }} /> : null;
  }

  return pure ? memo(WithTracker) : WithTracker;
};

Again, this would deserve actual real-world batte-testing, but it seems to be working fairly well – and the code is way simpler to grok than the current react-meteor-data :heart_eyes:

example usage :

function MyComponent({ docId }) {
  const doc = useTracker(() => Documents.findOne(docId), [docId]);
  return doc ? <div><h1>{doc.title}</h1>{doc.body}</div> : <Spinner/>
}
8 Likes