-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Middleware #1160
Middleware #1160
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit a81bc8c:
|
I think the original key should be passed to middlewares... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work 👏 👏
I've found some type errors in the middleware tests and fixed type errors and added types to middlewares in tests.
I'm also confused the behavior for multiple middlewares and modifying keys.
The following test now fails. Isn't it possible to modify keys in middlewares?
it('should pass modified keys to the next middlewares and useSWR', async () => {
const key = createKey()
const createDecoratingKeyMiddleware = (c: string): Middleware => useSWRNext => (k, fn, config) => {
return useSWRNext(`${c}${k}${c}` , fn, config)
}
function Page() {
const { data } = useSWR(key, () => {
return createResponse(key)
}, {
middlewares: [createDecoratingKeyMiddleware('!'), createDecoratingKeyMiddleware('#')]
})
return <div>hello, {data}</div>
}
render(<Page />)
screen.getByText('hello,')
await screen.findByText(`hello, #!${key}!#`) // actual: the key is not decorated
})
I've also created a sample middleware for the status middleware you mentioned in #1215 (comment) I could implement it, but it was difficult to extend the return type of it('should pass modified keys to the next middlewares and useSWR', async () => {
const statusMiddleware: Middleware = useSWRNext => (k, fn, config) => {
const result = useSWRNext(k, fn, config);
return {
...result,
status: result.data ? 'ready': 'fetching'
}
}
function Page() {
// @ts-ignore the status property should be typed.
const { data, status } = useSWR('key', () => {
return createResponse('data')
}, {
middlewares: [statusMiddleware]
})
return <div>{status}:hello, {data}</div>
}
render(<Page />)
screen.getByText('fetching:hello,')
await screen.findByText(`ready:hello, data`)
}) |
Co-authored-by: Toru Kobayashi <[email protected]>
Co-authored-by: Toru Kobayashi <[email protected]>
Thanks for contributing another test case, Toru!
I think that's because the fetcher directly returned the original key from the outer context: useSWR(key, () => {
return createResponse(key)
}) If we change it to this, it will work: useSWR(key, (k) => {
return createResponse(k)
}) Also, the result should be |
Co-authored-by: Toru Kobayashi <[email protected]>
Yeah absolutely. Ideally the config of custom SWR hooks should be extendable too... I don't know if there's a good way to do it with TS though. |
I misunderstood it. Thank you!
The easiest way to do it is to add additional type parameters to function Page() {
type CustomSWRResponse = SWRResponse<string, any> & { status: string }
const { data, status } = useSWR<string, any, CustomSWRResponse>('key', () => {
return createResponse('data')
}, {
middlewares: [statusMiddleware]
})
return <div>{status}:hello, {data}</div>
} I don't think it's a blocker to merge this, so feel free to go forward👍 |
Yeah, I think it would be very tricky to directly extend the types of key, fn, config, and return value of |
This is an implementation of #875, #172, #1030.
Middlewares
The new option
config.middlewares
is now supported, for example:Middlewares can be extended via multiple contexts and/or per-hook config, for example:
Middlewares will be executed from inner to outer (this will be extremely helpful for custom SWR hooks that override
key
,fn
, orconfig
. So higher level middlewares don't need to care about the details):Concerns
Which key should be passed to the middlewares (original or serialized)?Original, so the middleware will have more flexibility.Ismiddlewares
a good name? How aboutplugins
/use
?Notes
This PR refactors some internal APIs such as
useArgs
. Those will simplify the process of building other hooks on top of SWR.Also, the ESLint rule
react/prop-types
is now disabled given we have TypeScript already.Credits to https://redux.js.org/understanding/history-and-design/middleware and #1030 (comment) for the idea and implementation discussions.