Description
Made withAuth
to not have to mess with <App>
and give example of making HOC. Not feeling like either reason is very important.
Globals?
Inspired by DHH's series on writing software well, in an episode recommending judicious use of globals, eg for the current user.
Could be used for login
/logout
functions.
- Pro: Easy
- Con: Testing—for various forms of testing (including explicit unit tests and things like storybook), you then have to mock out the globals.
// CurrentUserQuery.js
export let login, logout
class CurrentUserQuery extends Component
constructor() {
login = this.login
logout = this.logout
}
login = () =>
logout = () =>
So that eg in Profile.js
you can:
import { login, logout } from './CurrentUserQuery'
instead of getting them as props.
Prop drilling vs HOC vs Context/unstated
Need a reactive data source for loading
& currentUser
, so can't do globals.
Reusable query
Could do a withUser()
HOC that provides them through graphql()
to any component that needs it. All using default cache-first, and deduplication should combine them into one query, while also maintaining data.loading
/loadingUser
.
- Pro: concise. Using Apollo store like the global variable it is
- Con: how to incorporate
loggingIn
intoloading
? In the single-usewithAuth
, it's defined as:loading={loading || this.state.loggingIn}
class Profile extends Component {
...
}
export default withUser(Profile)
(or alternatively could make a reusable <WithUser>
query component, but that takes more characters and indentation to use)
Prop drilling
A single normal query at the top. Lot of drilling. It's nice for testing, but not nice to read/write. Would personally prefer to avoid.
<CurrentUserQuery>
{({ loading, error, data }) => (
<App loadingUser={loading} currentUser={data.currentUser} />
)}
</CurrentUserQuery>
Context/unstated
- Pro: no drilling
- Con: verbose