Skip to content

Instantly share code, notes, and snippets.

@CaptainN
Last active January 2, 2020 06:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CaptainN/51d89c0a752f94b07132cc1bf1bd6b3f to your computer and use it in GitHub Desktop.
Save CaptainN/51d89c0a752f94b07132cc1bf1bd6b3f to your computer and use it in GitHub Desktop.
example code for meteor hook
// Hook, basic use, everything in one component
const MyAccount = () => {
const { user, isLoggedIn } = useTracker(() => {
const user = Meteor.user()
const userId = Meteor.userId()
return {
user,
userId,
isLoggedIn: !!userId
}
}, [])
if (!isLoggedIn) {
return <div>
<Link to="/register">Create an Account</Link>
<Link to="/login">Log in</Link>
</div>
}
return <div>
<h1>{user.username}</h1>
<a href="#" onClick={(e) => { e.preventDefault(); Meteor.logout(); }}>Log out</a>
</div>)
}
// With prefab account hook
// Create a reusable hook
const useAccount = () => useTracker(() => {
const user = Meteor.user()
const userId = Meteor.userId()
return {
user,
userId,
isLoggedIn: !!userId
}
}, [])
// simply use the hook
const MyAccount = () => {
const { user, isLoggedIn } = useAccount()
if (!isLoggedIn) {
return <div>
<Link to="/register">Create an Account</Link>
<Link to="/login">Log in</Link>
</div>
}
return <div>
<h1>{user.username}</h1>
<a href="#" onClick={(e) => { e.preventDefault(); Meteor.logout() }}>Log out</a>
</div>
}
// Create the Container
const withMyAccount = withTracker((props) => {
const user = Meteor.user()
const userId = Meteor.userId()
return {
user,
userId,
isLoggedIn: !!userId
}
})
// Create the component
const MyAccountComponent = ({user, isLoggedIn} => {
if (!isLoggedIn) {
return <div>
<Link to="/register">Create an Account</Link>
<Link to="/login">Log in</Link>
</div>
}
return <div>
<h1>{user.username}</h1>
<a href="#" onClick={(e) => { e.preventDefault(); Meteor.logout() }}>Log out</a>
</div>
})
// Now create the containerized component - gets messy with more than one container
const MyAccount = withMyAccount(MyAccountComponent)
// A more complex component with subscribe and queries and complex deps
const MyPage = ({ pageId }) => {
const {page, isLoading} = useTracker(() => {
const handle = Meteor.subscribe('pages', pageId)
return {
isLoading: !handle.ready(),
page: Pages.findOne(pageId)
}
}, [pageId])
if (isLoading) {
return <div>Page is loading</div>
}
return <div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(page.content)}} />
</div>
}
// Breaking the more complex component apart
const MyPage = ({ pageId }) => {
const isLoading = useTracker(
() => !Meteor.subscribe('pages', pageId).ready(),
[pageId]
)
const page = useTracker(
() => Pages.findOne(pageId),
[pageId]
)
if (isLoading) {
return <div>Page is loading</div>
}
return <div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(page.content)}} />
</div>
}
// the same, with generic hooks
const usePageSubscribe = (pageId) => useTracker(
() => !Meteor.subscribe('pages', pageId).ready(),
[pageId]
)
const usePage = (pageId) => useTracker(
() => Pages.findOne(pageId),
[pageId]
)
const MyPage = ({ pageId }) => {
const isLoading = usePageSubscribe(pageId)
const page = usePage(pageId)
if (isLoading) {
return <div>Page is loading</div>
}
return <div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(page.content)}} />
</div>
}
// Same - with Suspense!
const usePageSubscribe = (pageId) => useTracker(
() => {
// This is a little tricky. We want to be able to resolve the promise
// when the subscription is ready, but we only want to throw if the
// subscription is not ready yet.
let handle
const promise = new Promise((resolve, reject) => {
handle = Meteor.subscribe('pages', pageId, () => { resolve(false) })
})
const isLoading = !handle.ready()
if (isLoading) {
throw promise
}
return isLoading
},
[pageId]
)
const usePage = (pageId) => useTracker(
() => Pages.findOne(pageId),
[pageId]
)
const MyPage = ({ pageId }) => {
// Now usePageSubscribe will throw to the parent Suspense
// when the subscription is not ready!
const isLoading = usePageSubscribe(pageId)
const page = usePage(pageId)
return <div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(page.content)}} />
</div>
}
const ExampleUsingSuspense = () => {
return <Suspsene fallback={<Loading />}>
<MyPage pageId='my-page-id' />
</Suspsene>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment