Open ecwyne opened 4 years ago
@ecwyne Thanks for the note 👍 I've actually been thinking about that as well. When I refactored useDatabase
to be useFaunaClient
I was considering changing the former to provide some Context values to use throughout the app. I'll certainly take a look at the references you provided me.
My think is if we instantiate a Client with useFaunaClient
we can pipe it to the sub-tree with a Context provider for components that care. This way, we could also use different clients for different parts of the app if we don't want all the data living in one DB.
What do you think?
I definitely think it's possible to make it so that you can pass different client parameters to different sub-trees and merge them with the configurations from parent providers.
Eg.
<FaunaProvider config={{ secret: 'secret1' }}>
<ComponentOne />
<FaunaProvider config={{ secret: 'secret2' }}>
<ComponentTwo />
</FaunaProvider>
<FaunaProvider config={{ observer: console.log }}>
<ComponentThree />
</FaunaProvider>
</FaunaProvider>
I would suggest having a useFaunaClient
hook that uses the configuration options provided in context to create the Client
instance. It would not be possible to merge configurations if you're passing down the Client
instance itself
const useFaunaClient = () => {
const { config } = useContext(FaunaContext);
return new Client(config);
};
I definitely think it's possible to make it so that you can pass different client parameters to different sub-trees and merge them with the configurations from parent providers.
Eg.
<FaunaProvider config={{ secret: 'secret1' }}> <ComponentOne /> <FaunaProvider config={{ secret: 'secret2' }}> <ComponentTwo /> </FaunaProvider> <FaunaProvider config={{ observer: console.log }}> <ComponentThree /> </FaunaProvider> </FaunaProvider>
Awesome. I was definitely thinking something along these lines 🙌 I can imagine folks wanting to isolate data from different parts of their app in different DBs, which they can provide to pages/components through a Context.Provider
.
I would suggest having a
useFaunaClient
hook that uses the configuration options provided in context to create theClient
instance. It would not be possible to merge configurations if you're passing down theClient
instance itselfconst useFaunaClient = () => { const { config } = useContext(FaunaContext); return new Client(config); };
Originally, I was thinking useFaunaClient
would work as it does now and that you'd then pass it into a useDatabase
hook. That hook would return a Context and a Context provider with the Client instance as its value.
Something like this:
// App.js
const client = useFaunaClient(KEY)
const [DatabaseProvider] = useDatabase(client)
return (
<DatabaseProvider>
<Component1 />
<Component2 />
</DatabaseProvider>
)
// Component2
const client = useFaunaClient(KEY)
const [DataContext] = useDatabase(client)
const data = useContext(DataContext)
What do you think? Certainly not married to this implementation 😅
As written useFaunaClient
requires you to keep track of a secret throughout your app and pass it every time.
I believe useFaunaClient
shouldn't take any arguments at all and returns a client
based on the context it's being run in. This is how useApolloClient
works
Also, I'm not sure what you mean by Database
. (In your example useDatabase()
returns either a [DatabaseProvider]
or [DataContext]
?
In practice, I almost never think about the Fauna idea of a Database
. I use a client
to read Documents
from Collections
, match Indexes
, and call Functions
.
Instead of providing a
Client
instance to each hook, it would be much cleaner and more intuitive to provide client parameters through context.Prior art: vercel/swr @apollo/client tannerlinsley/react-query