Skip to content

Commit 2c30765

Browse files
author
Alex Cory
committed
added useQuery, useMutation, Provider, and URLContext
1 parent b1410f8 commit 2c30765

8 files changed

+104
-6
lines changed

src/Provider.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { useState, useEffect, useMemo, ReactElement } from 'react'
2+
import useSSR from 'use-ssr'
3+
import URLContext from './URLContext'
4+
5+
interface FetchProviderProps {
6+
url?: string,
7+
options?: RequestInit,
8+
children: ReactElement,
9+
graphql?: boolean,
10+
}
11+
12+
export const Provider = ({ url, options, graphql = false, children }: FetchProviderProps): ReactElement => {
13+
const { isBrowser } = useSSR()
14+
const [defaultURL, setURL] = useState(url || '')
15+
16+
useEffect(() => {
17+
if (isBrowser && !url) setURL(window.location.origin)
18+
}, [url, isBrowser])
19+
20+
const defaults = useMemo(
21+
() => ({
22+
url: defaultURL,
23+
options: options || {},
24+
graphql, // TODO: this will make it so useFetch(QUERY || MUTATION) will work
25+
}),
26+
[url, options, graphql],
27+
)
28+
29+
return (
30+
<URLContext.Provider value={defaults}>
31+
{children}
32+
</URLContext.Provider>
33+
)
34+
}

src/URLContext.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { createContext } from 'react'
2+
3+
4+
export const URLContext = createContext({
5+
url: typeof window !== 'undefined' ? window.location.origin : '',
6+
options: {},
7+
graphql: false, // TODO: this will make it so useFetch(QUERY || MUTATION) will work
8+
})
9+
10+
export default URLContext

src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ export * from './usePost'
55
export * from './usePut'
66
export * from './usePatch'
77
export * from './useDelete'
8+
export * from './useMutation'
9+
export * from './useQuery'
10+
export * from './Provider'
11+
export * from './URLContext'

src/useFetch.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useEffect, useState, useCallback, useRef, MutableRefObject, useMemo } from 'react'
1+
import { useEffect, useState, useCallback, useRef, useContext, MutableRefObject, useMemo } from 'react'
2+
import URLContext from './URLContext'
23

34
const isObject = (obj: any) => Object.prototype.toString.call(obj) === '[object Object]'
45

@@ -10,8 +11,11 @@ export interface Options {
1011
baseUrl?: string
1112
}
1213

13-
export function useFetch(arg1: string | Options & RequestInit, arg2: Options) {
14-
let url: string | null = null
14+
type useFetchArg1 = string | Options & RequestInit
15+
16+
export function useFetch(arg1: useFetchArg1, arg2?: Options | RequestInit) {
17+
const context = useContext(URLContext)
18+
let url: string | null = context.url || null
1519
let options = {} as { signal?: AbortSignal | null } & RequestInit
1620
let onMount = false
1721
let baseUrl = ''
@@ -24,15 +28,19 @@ export function useFetch(arg1: string | Options & RequestInit, arg2: Options) {
2428
let { url, onMount, timeout, baseUrl, ...rest } = opts
2529
options = { signal: undefined, ...rest }
2630
}
27-
if (opts.url) url = opts.url
31+
if (context.url) url = context.url
32+
if (opts.url) url = opts.url || context.url
2833
if (opts.onMount) onMount = opts.onMount
2934
if (opts.method) method = opts.method
3035
if (opts.baseUrl) baseUrl = opts.baseUrl
3136
}
3237

3338
if (typeof arg1 === 'string') {
34-
url = arg1
35-
if (isObject(arg2)) handleOptions(arg2)
39+
// if we have a default url from context, and
40+
// arg1 is a string, we treat it as a relative route
41+
url = context.url ? context.url + arg1 : arg1
42+
43+
if (arg2 && isObject(arg2)) handleOptions(arg2)
3644
} else if (isObject(arg1)) {
3745
handleOptions(arg1)
3846
}

src/useMutation.js

Whitespace-only changes.

src/useMutation.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import useFetch, { URLContext } from '.'
2+
import { useContext, useCallback } from 'react';
3+
4+
5+
export const useMutation = (arg1: string, arg2: string) => {
6+
const context = useContext(URLContext)
7+
8+
let url = arg1
9+
let MUTATION = arg2
10+
11+
if (arg1 && !arg2 && context.url) {
12+
url = context.url
13+
MUTATION = arg1
14+
}
15+
16+
const request = useFetch(url)
17+
18+
const mutate = useCallback(inputs => request.mutate(MUTATION, inputs), [])
19+
20+
return Object.assign([request.data, request.loading, request.error, mutate], { ...request, mutate })
21+
}

src/useQuery.js

Whitespace-only changes.

src/useQuery.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import useFetch, { URLContext } from '.'
2+
import { useContext, useCallback } from 'react';
3+
4+
5+
export const useQuery = (arg1: string, arg2: string) => {
6+
const context = useContext(URLContext)
7+
8+
let url = arg1
9+
let QUERY = arg2
10+
11+
if (arg1 && !arg2 && context.url) {
12+
url = context.url
13+
QUERY = arg1
14+
}
15+
16+
const request = useFetch(url)
17+
18+
const query = useCallback(inputs => request.query(QUERY, inputs), [])
19+
20+
return Object.assign([request.data, request.loading, request.error, query], { ...request, query })
21+
}

0 commit comments

Comments
 (0)