Skip to content

Proposal for react-meteor-hooks #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/react-meteor-hooks/.versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
babel-compiler@7.0.0
babel-runtime@1.2.0
dynamic-import@0.3.0
ecmascript@0.10.0
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.6.0
ecmascript-runtime-server@0.5.0
http@1.4.0
meteor@1.8.2
modules@0.11.3
modules-runtime@0.9.1
promise@0.10.1
react-meteor-data@0.2.16
tmeasday:check-npm-versions@0.3.2
tracker@1.1.3
url@1.2.0
59 changes: 59 additions & 0 deletions packages/react-meteor-hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## `react-meteor-data`

This package provides an integration between React Hooks and [`Tracker`](https://atmospherejs.com/meteor/tracker), Meteor's reactive data system.

### Install

To install the package, use `meteor add`:

```bash
meteor add react-meteor-hooks
```

You'll also need to install `react` if you have not already:

```bash
npm install --save react@16.7.0.alpha.0
```

### Hooks

**`useMeteorSubscription`**

It takes all arguments you would put into `Meteor.subscribe` and runs
the subscription and `ready()` checks in a `useEffect` and returns the
value of a state hook for `ready()`.

**`useMeteorData`**

This function takes a function as first parameter and runs that as an
effect hook within the meteor tracker. The second parameter is an
array of inputs that influence the effect hook.

It returns the value of the state hook that represents the return
value of the given function. This can either be an object to be
destructured later or a single value (array of collection documents or
single collection document).

### Usage

This package exports the hooks `useMeteorSubscription` and `useMeteorData`.

```js
export const Page = function (props) {
const loading = useMeteorSubscription('links');
const links = useMeteorData(() => Links.find().fetch());

if(loading) return (<div>Loading links ...</div>);

return (
<ul>
{links.map((link) => (
<li key={link._id}>
<a href={link.url} target="_blank">{link.title}</a>
</li>
))}
</ul>
);
}
```
18 changes: 18 additions & 0 deletions packages/react-meteor-hooks/package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Package.describe({
name: 'react-meteor-hooks',
summary: 'Proposal for react-hooks getting meteor data',
version: '0.1.0',
documentation: 'README.md',
git: 'https://github.com/meteor/react-packages',
});

Package.onUse(function (api) {
api.versionsFrom('1.3');
api.use('tracker');
api.use('ecmascript');
api.use('tmeasday:check-npm-versions@0.3.2');

api.export([]);

api.mainModule('react-meteor-hooks.jsx');
});
8 changes: 8 additions & 0 deletions packages/react-meteor-hooks/react-meteor-hooks.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';

checkNpmVersions({
react: '16.7.0-alpha.0',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to set the react version to current stable in this case 16.8.3

}, 'react-meteor-hooks');

export { default as useMeteorSubscription } from './useMeteorSubscription.jsx';
export { default as useMeteorData } from './useMeteorData.jsx';
35 changes: 35 additions & 0 deletions packages/react-meteor-hooks/useMeteorData.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { useEffect, useState } from 'react';

let useMeteorData;

if (Meteor.isServer) {
// When rendering on the server, we don't want to use the Tracker.
// We only do the first rendering on the server so we can get the data right away
useMeteorData = getMeteorData => getMeteorData();
} else {
useMeteorData = (getMeteorData, inputs = []) => {
const [meteorData, setMeteorData] = useState(getMeteorData());
let computation;

const cleanUp = () => {
computation.stop();
computation = null;
}

useEffect(() => {
if(computation) cleanUp();

Tracker.autorun((currentComputation) => {
computation = currentComputation;
setMeteorData(getMeteorData());
});

return cleanUp;
}, inputs);

return meteorData;
}
}
export default useMeteorData;
40 changes: 40 additions & 0 deletions packages/react-meteor-hooks/useMeteorSubscription.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { useEffect, useState } from 'react';

let useMeteorSubscription;

if (Meteor.isServer) {
// When rendering on the server, we don't want to use the Tracker.
// The subscription is always ready on the server.
useMeteorSubscription = () => true;
} else {
useMeteorSubscription = (publication, ...parameters) => {
const [loading, setLoading] = useState(true);
let handle, computation;

const cleanUp = () => {
handle && handle.stop();
handle = null;
computation && computation.stop();
computation = null;
}

useEffect(() => {
if(computation) cleanUp();

Tracker.autorun((currentComputation) => {
computation = currentComputation;

handle = Meteor.subscribe(publication, ...parameters);
setLoading(!handle.ready());
});

return cleanUp;
}, [publication, ...parameters]);

return loading;
}
}

export default useMeteorSubscription;