Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d8ad782
Use React.DependencyList instead of Array<any>
CaptainN Oct 19, 2020
c4c9f62
Add an accounts hook package
CaptainN Oct 21, 2020
b1281d1
Add react-meteor-state hook package
CaptainN Oct 21, 2020
5932980
Add react-mongo slim hooks package
CaptainN Oct 21, 2020
7460169
Always render on commit and apply feedback on deps
CaptainN Nov 1, 2020
0b99ffe
Fix subscriptions not closed when stopping computation
rijk Nov 2, 2020
d94b254
Merge pull request #302 from rijk/new-hooks
CaptainN Nov 2, 2020
98d80d2
Voidable sub factory, reactive ready, and a Readme
CaptainN Nov 3, 2020
b9404da
Use factoryless useSubscription other improvements
CaptainN Nov 8, 2020
e075fba
Help Typescript keep track of type of refs
CaptainN Nov 9, 2020
0d9f3ba
Fix ready() doesn't update, and update react-mongo type def
CaptainN Nov 10, 2020
e11f8bc
Remove unneeded complexity in useSubscription
CaptainN Nov 11, 2020
d5b5f8e
Use memoized refs.params to reduce useEffect churn
CaptainN Nov 18, 2020
f59dd39
Make useCursor memoize fetch results
CaptainN Nov 20, 2020
ba67ebb
First run after deps change returns the right data
CaptainN Nov 21, 2020
37ff546
Fix initial data after deps change behavior
CaptainN Nov 22, 2020
783dad9
Add useFind, useFindOne, useCount
CaptainN Nov 23, 2020
9aec19d
Make useFindOne and useCount accept factory methods
CaptainN Nov 24, 2020
754953a
Update useTracker cleaner impl, and clean up tests
CaptainN Nov 26, 2020
9fa3df9
Apply feedback to useFind and useSubscription
CaptainN Nov 26, 2020
9ed323f
Check for cursor on server too
CaptainN Nov 29, 2020
9dabef9
Clean up type notation, pass comp to reactiveFn
CaptainN Nov 29, 2020
b06c4cd
Fix failing resubscribe tests by forcing full flush cylce
CaptainN Dec 1, 2020
6d056ec
Improve signal to noice of resubscribe tests
CaptainN Dec 1, 2020
51b2f38
Update packages and add typescript gen script
CaptainN Dec 1, 2020
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
40 changes: 40 additions & 0 deletions packages/react-mongo/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
meteor/react-mongo
==================

```
meteor add meteor/react-mongo
```

A set of hooks for using Meteor's Mini Mongo Collections and pub/sub.

There are two hooks

| Hook | Function
| ---- | --------
| useSubscription | Used to set up a Meteor subscription. In SSR, this hook is responsible for capturing data to be sent to the client for hydration.
| useCursor | Manages the lifecycle of a Mongo Cursor

Both methods accept a factory method, and deps.

## useSubscription(factory, deps)

`useSubscription` takes a factory method, which should return a subscription handle, and a deps array. It can also return `void` to conditionally set up no subscription. The hook returns a subscription handle with a reactive `ready` method.

Invoking the `ready()` handle method will cause the hook to update react when the subscription becomes available.

### Example

```jsx
import React from 'react'
import { useSubscription } from 'meteor/react-mongo'

const MyComponent = ({ id = null }) => {
const subscription = useSubscription(() => {
if (id) return Meteor.subscribe(id)
}, [id])

return <div>
{
subscription.ready()
? 'content ready'
: 'loading...'
}
</div>
}
```
41 changes: 31 additions & 10 deletions packages/react-mongo/react-mongo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,54 @@ import { useEffect, useMemo, useReducer, useRef, DependencyList } from 'react'
const fur = (x: number): number => x + 1
const useForceUpdate = () => useReducer(fur, 0)[1]

const useSubscriptionClient = (factory: () => Meteor.SubscriptionHandle, deps: DependencyList = []) => {
const useSubscriptionClient = (factory: () => Meteor.SubscriptionHandle | void, deps: DependencyList= []) => {
const forceUpdate = useForceUpdate()
const subscription = useRef<Meteor.SubscriptionHandle>({
stop() {},
ready: () => false
const { current: refs } = useRef<{
handle?: Meteor.SubscriptionHandle,
updateOnReady: boolean
}>({
handle: {
stop () {
refs.handle?.stop()
},
ready () {
refs.updateOnReady = true
return refs.handle?.ready()
}
},
updateOnReady: false
})

useEffect(() => {
const computation = Tracker.autorun(() => {
subscription.current = factory()
if (subscription.current.ready()) forceUpdate()
})
// Use Tracker.nonreactive in case we are inside a Tracker Computation.
// This can happen if someone calls `ReactDOM.render` inside a Computation.
// In that case, we want to opt out of the normal behavior of nested
// Computations, where if the outer one is invalidated or stopped,
// it stops the inner one.
const computation = Tracker.nonreactive(() => (
Tracker.autorun(() => {
refs.handle = factory()
if (!refs.handle) return
if (refs.updateOnReady && refs.handle.ready()) {
forceUpdate()
}
})
))

return () => {
computation.stop()
}
}, deps)

return subscription.current
return refs.handle
}

const useSubscriptionServer = (): Meteor.SubscriptionHandle => ({
stop() {},
ready() { return true }
})

export const useSubscription = (factory: () => Meteor.SubscriptionHandle, deps: DependencyList = []) => (
export const useSubscription = (factory: () => Meteor.SubscriptionHandle | void, deps: DependencyList = []) => (
Meteor.isServer
? useSubscriptionServer()
: useSubscriptionClient(factory, deps)
Expand Down
7 changes: 6 additions & 1 deletion packages/react-mongo/types/react-mongo.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { DependencyList } from 'react';
export declare const useSubscription: (factory: () => Meteor.SubscriptionHandle, deps?: DependencyList) => Meteor.SubscriptionHandle;
declare type UseSubscriptionOptions = {
deps?: DependencyList;
updateOnReady?: boolean;
};
export declare const useSubscription: (factory: () => Meteor.SubscriptionHandle | void, deps?: DependencyList | UseSubscriptionOptions) => void;
export declare const useCursor: <T = any>(factory: () => Mongo.Cursor<T>, deps?: DependencyList) => Mongo.Cursor<T>;
export {};