use-fauna icon indicating copy to clipboard operation
use-fauna copied to clipboard

[Discussion] Provide configuration through Context API

Open ecwyne opened this issue 4 years ago • 6 comments

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

ecwyne avatar Aug 12 '20 17:08 ecwyne

@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?

ryancharris avatar Aug 14 '20 12:08 ryancharris

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>

ecwyne avatar Aug 14 '20 17:08 ecwyne

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);
};

ecwyne avatar Aug 14 '20 17:08 ecwyne

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.

ryancharris avatar Aug 14 '20 21:08 ryancharris

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);
};

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 😅

ryancharris avatar Aug 14 '20 21:08 ryancharris

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.

ecwyne avatar Aug 14 '20 23:08 ecwyne