Last active
November 16, 2018 18:31
-
-
Save cray0000/534efd859f5d6ff6e398b6d754183fcc to your computer and use it in GitHub Desktop.
react-sharedb HOOKS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a documented verison of the first example | |
export function Simple ({gameId}) { | |
// Subscribe to `game` from mongo. You have to explicitely wait for all `useDoc` and `useQuery` to finish | |
let [game, $game] = useDoc('games', gameId) | |
// Wait for `game` subscription to finish | |
if (!game) return null // <Loading /> | |
function updateGameTitle (event) { | |
$game.set('title', event.target.value) | |
} | |
return ( | |
<div> | |
<h1>{game.title}</h1> | |
<label> | |
Edit game title: | |
<input type='text' value={game.title} onChange={updateGameTitle} /> | |
</label> | |
</div> | |
) | |
} | |
export function MultipleSubscribeWaves ({gameId}) { | |
// Private value, which lives only in this component's private scope model (`$store`) | |
let [secret, $secret] = useValue('My Secret') | |
// Get userId from local path `_session.userId` (synchronous). | |
let [userId, $userId] = useLocal('_session.userId') | |
// And then subscribe to this user's document by id from mongo. | |
// Since it might get data from mongo, this operation is async, so we need to wait until it completes | |
// | |
// You have to explicitely wait for any asynchronous subscription (`useDoc`, `useQuery`) to finish. | |
// Otherwise you will end up with the "can't read `foo` of undefined" errors. | |
// While the subscription didn't finish, the data returned from the `useDoc` and `useQuery` is just an `[]`. | |
let [user, $user] = useDoc('users', userId) | |
// We have to wait for `user` subscription to finish, but the next subscription we are going to do (`game`) | |
// does not depend on `user`. So to make subscriptions finish faster, lets subscribe to `game` right away. | |
// And then we'll wait for both -- the `user` and the `game` subscriptions to finish. | |
// Subscribe to the game document from mongo (async). | |
// This subscription will start in parallel to our `user` subscription. | |
let [game, $game] = useDoc('games', gameId) | |
// Wait for both `game` and `user` subscriptions to finish | |
if (!(game && user)) return null // <Loading /> | |
// Subscribe to all players in the game. We take `playerIds` data from the previous subscription, | |
// that's why we had to wait for the `game` to finish first and can't just subscribe to `players` in parallel. | |
let [players, $players] = useQuery('players', {_id: {$in: game.playerIds}}) | |
// Wait for `players` since for next subscription we'll have to use it | |
if (!players) return null // <Loading /> | |
// Subscribe to each player's user document. | |
let [users, $users] = useQuery('users', {_id: {$in: players.map(i => i.userId)}}) | |
// Wait for all the remaining subscriptions before proceeding to the render code. | |
if (!users) return null // <Loading /> | |
function updateSecret (event) { | |
$secret.set(event.target.value) | |
} | |
function updateName (event) { | |
$user.set('name', event.target.value) | |
} | |
return ( | |
<div> | |
<label> | |
Secret: | |
<input type='text' vaule={code} onChange={updateSecret} /> | |
</label> | |
<label> | |
My User Name: | |
<input type='text' value={user.name} onChange={updateName} /> | |
</label> | |
<h1>Game {game.title}</h1> | |
<h2>Users in game:</h2> | |
<p>{users.map(i => i.name).join(', ')}</p> | |
</div> | |
) | |
} | |
export function MultipleSubscribeWavesUseSubscribe ({gameId}) { | |
// Same subscriptions as in previous component, but using a single useSubscribe hook, | |
// which also lets you wait for everything using the `ready` magic flag. | |
let { | |
ready | |
secret, $secret, | |
userId, | |
user, $user, | |
game, | |
players, | |
users | |
} = useSubscribe(() => ({ | |
secret: useValue('My Secret'), | |
userId: useLocal('_session.userId'), | |
user: useDoc('users', userId), | |
game: useDoc('games', gameId) | |
}), () => ({ | |
players: useQuery('players', {_id: {$in: game.playerIds}}) | |
}), () => ({ | |
users: useQuery('users', {_id: {$in: players.map(i => i.userId)}}) | |
})) | |
if (!ready) return null // <Loading /> | |
function updateSecret (event) { | |
$secret.set(event.target.value) | |
} | |
function updateName (event) { | |
$user.set('name', event.target.value) | |
} | |
return ( | |
<div> | |
<label> | |
Secret: | |
<input type='text' vaule={code} onChange={updateSecret} /> | |
</label> | |
<label> | |
My User Name: | |
<input type='text' value={user.name} onChange={updateName} /> | |
</label> | |
<h1>Game {game.title}</h1> | |
<h2>Users in game:</h2> | |
<p>{users.map(i => i.name).join(', ')}</p> | |
</div> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment