Skip to content
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

update to latest remark-typescript-tools #3311

Merged
merged 3 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions docs/rtk-query/api/created-api/endpoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ When dispatching an action creator, you're responsible for storing a reference t

#### Example

```tsx title="initiate query example"
```tsx no-transpile title="initiate query example"
import { useState } from 'react'
import { useAppDispatch } from './store/hooks'
import { api } from './services/api'
Expand All @@ -119,7 +119,7 @@ function App() {
}
```

```tsx title="initiate mutation example"
```tsx no-transpile title="initiate mutation example"
import { useState } from 'react'
import { useAppDispatch } from './store/hooks'
import { api, Post } from './services/api'
Expand Down Expand Up @@ -187,7 +187,7 @@ Each call to `.select(someCacheKey)` returns a _new_ selector function instance.

#### Example

```tsx title="select query example"
```tsx no-transpile title="select query example"
import { useState, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from './store/hooks'
import { api } from './services/api'
Expand All @@ -198,9 +198,10 @@ function App() {
// highlight-start
// useMemo is used to only call `.select()` when required.
// Each call will create a new selector function instance
const selectPost = useMemo(() => api.endpoints.getPost.select(postId), [
postId,
])
const selectPost = useMemo(
() => api.endpoints.getPost.select(postId),
[postId]
)
const { data, isLoading } = useAppSelector(selectPost)
// highlight-end

Expand All @@ -223,7 +224,7 @@ function App() {
}
```

```tsx title="select mutation example"
```tsx no-transpile title="select mutation example"
import { useState, useMemo } from 'react'
import { skipToken } from '@reduxjs/toolkit/query'
import { useAppDispatch, useAppSelector } from './store/hooks'
Expand Down
17 changes: 8 additions & 9 deletions docs/rtk-query/usage-with-typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ export const api = createApi({
export const { useGetPostQuery } = api
```

```tsx title="Using skip in a component"
```tsx no-transpile title="Using skip in a component"
import { useGetPostQuery } from './api'

function MaybePost({ id }: { id?: number }) {
Expand All @@ -486,7 +486,7 @@ While you might be able to convince yourself that the query won't be called unle

RTK Query provides a `skipToken` export which can be used as an alternative to the `skip` option in order to skip queries, while remaining type-safe. When `skipToken` is passed as the query argument to `useQuery`, `useQueryState` or `useQuerySubscription`, it provides the same effect as setting `skip: true` in the query options, while also being a valid argument in scenarios where the `arg` might be undefined otherwise.

```tsx title="Using skipToken in a component"
```tsx no-transpile title="Using skipToken in a component"
import { skipToken } from '@reduxjs/toolkit/query/react'
import { useGetPostQuery } from './api'

Expand Down Expand Up @@ -566,7 +566,7 @@ export interface SerializedError {
When using `fetchBaseQuery`, the `error` property returned from a hook will have the type `FetchBaseQueryError | SerializedError | undefined`.
If an error is present, you can access error properties after narrowing the type to either `FetchBaseQueryError` or `SerializedError`.

```tsx
```tsx no-transpile
import { api } from './services/api'

function PostDetail() {
Expand All @@ -587,10 +587,9 @@ function PostDetail() {
<div>{errMsg}</div>
</div>
)
}
else {
// you can access all properties of `SerializedError` here
return <div>{error.message}</div>
} else {
// you can access all properties of `SerializedError` here
return <div>{error.message}</div>
}
}

Expand All @@ -617,7 +616,7 @@ In order to safely access properties of the error, you must first narrow the typ
This can be done using a [type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
as shown below.

```tsx title="services/helpers.ts"
```tsx no-transpile title="services/helpers.ts"
import { FetchBaseQueryError } from '@reduxjs/toolkit/query'

/**
Expand All @@ -644,7 +643,7 @@ export function isErrorWithMessage(
}
```

```tsx title="addPost.tsx"
```tsx no-transpile title="addPost.tsx"
import { useState } from 'react'
import { useSnackbar } from 'notistack'
import { api } from './services/api'
Expand Down
4 changes: 2 additions & 2 deletions docs/rtk-query/usage/automated-refetching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ export const api = createApi({
export const { useGetPostsQuery, useGetPostQuery, useAddPostMutation } = api
```

```tsx title="App.tsx"
```tsx no-transpile title="App.tsx"
function App() {
const { data: posts } = useGetPostsQuery()
const [addPost] = useAddPostMutation()
Expand Down Expand Up @@ -742,7 +742,7 @@ export const api = createApi({
export const { useGetPostsQuery, useAddPostMutation, useGetPostQuery } = api
```

```tsx title="App.tsx"
```tsx no-transpile title="App.tsx"
function App() {
const { data: posts } = useGetPostsQuery()
const [addPost] = useAddPostMutation()
Expand Down
4 changes: 2 additions & 2 deletions docs/rtk-query/usage/cache-behavior.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Calling the `refetch` function will force refetch the associated query.

Alternatively, you can dispatch the `initiate` thunk action for an endpoint, passing the option `forceRefetch: true` to the thunk action creator for the same effect.

```tsx title="Force refetch example"
```tsx no-transpile title="Force refetch example"
import { useDispatch } from 'react-redux'
import { useGetPostsQuery } from './api'

Expand Down Expand Up @@ -197,7 +197,7 @@ export const api = createApi({
})
```

```tsx title="Forcing refetch on component mount"
```tsx no-transpile title="Forcing refetch on component mount"
import { useGetPostsQuery } from './api'

const Component = () => {
Expand Down
25 changes: 12 additions & 13 deletions docs/rtk-query/usage/error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ If your query or mutation happens to throw an error when using [fetchBaseQuery](

### Error Display Examples

```tsx title="Query Error"
```tsx no-transpile title="Query Error"
function PostsList() {
const { data, error } = useGetPostsQuery()

Expand All @@ -28,7 +28,7 @@ function PostsList() {
}
```

```tsx title="Mutation Error"
```tsx no-transpile title="Mutation Error"
function AddPost() {
const [addPost, { error }] = useAddPostMutation()

Expand All @@ -52,7 +52,7 @@ addPost({ id: 1, name: 'Example' })

:::

```tsx title="Manually selecting an error"
```tsx no-transpile title="Manually selecting an error"
function PostsList() {
const { error } = useSelector(api.endpoints.getPosts.select())

Expand Down Expand Up @@ -88,15 +88,14 @@ import { toast } from 'your-cool-library'
/**
* Log a warning and show a toast!
*/
export const rtkQueryErrorLogger: Middleware = (api: MiddlewareAPI) => (
next
) => (action) => {
// RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
if (isRejectedWithValue(action)) {
console.warn('We got a rejected action!')
toast.warn({ title: 'Async error!', message: action.error.data.message })
export const rtkQueryErrorLogger: Middleware =
(api: MiddlewareAPI) => (next) => (action) => {
// RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
if (isRejectedWithValue(action)) {
console.warn('We got a rejected action!')
toast.warn({ title: 'Async error!', message: action.error.data.message })
}

return next(action)
}

return next(action)
}
```
2 changes: 1 addition & 1 deletion docs/rtk-query/usage/manual-cache-updates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ callback for a mutation without a good reason, as RTK Query is intended to be us
your cached data as a reflection of the server-side state.
:::

```tsx title="General manual cache update example"
```tsx no-transpile title="General manual cache update example"
import { api } from './api'
import { useAppDispatch } from './store/hooks'

Expand Down
8 changes: 4 additions & 4 deletions docs/rtk-query/usage/migrating-to-rtk-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export type RootState = ReturnType<typeof store.getState>

In order to have the store accessible within our app, we will wrap our `App` component with a [`Provider`](https://react-redux.js.org/api/provider) component from `react-redux`.

```tsx title="src/index.ts"
```tsx no-transpile title="src/index.ts"
import { render } from 'react-dom'
// highlight-start
import { Provider } from 'react-redux'
Expand Down Expand Up @@ -223,9 +223,9 @@ export type RootState = {
pokemon: typeof initialPokemonSlice
}

export declare const store: EnhancedStore<RootState>
export declare const store: EnhancedStore<RootState>
export type AppDispatch = typeof store.dispatch
export declare const useAppDispatch: () => (...args: any[])=> any;
export declare const useAppDispatch: () => (...args: any[]) => any

// file: src/hooks.ts
import { useEffect } from 'react'
Expand Down Expand Up @@ -276,7 +276,7 @@ Our implementation below provides the following behaviour in the component:
- When our component is mounted, if a request for the provided pokemon name has not already been sent for the session, send the request off
- The hook always provides the latest received `data` when available, as well as the request status booleans `isUninitialized`, `isPending`, `isFulfilled` & `isRejected` in order to determine the current UI at any given moment as a function of our state.

```tsx title="src/App.tsx"
```tsx no-transpile title="src/App.tsx"
import * as React from 'react'
// highlight-start
import { useGetPokemonByNameQuery } from './hooks'
Expand Down
8 changes: 6 additions & 2 deletions docs/rtk-query/usage/mutations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ const api = createApi({
// Pick out data and prevent nested properties in a hook or selector
transformResponse: (response: { data: Post }, meta, arg) => response.data,
// Pick out errors and prevent nested properties in a hook or selector
transformErrorResponse: (response: { status: string | number }, meta, arg) => response.status,
transformErrorResponse: (
response: { status: string | number },
meta,
arg
) => response.status,
invalidatesTags: ['Post'],
// onQueryStarted is useful for optimistic updates
// The 2nd parameter is the destructured `MutationLifecycleApi`
Expand Down Expand Up @@ -177,7 +181,7 @@ When using `fixedCacheKey`, the `originalArgs` property is not able to be shared

This is a modified version of the complete example you can see at the bottom of the page to highlight the `updatePost` mutation. In this scenario, a post is fetched with `useQuery`, and then an `EditablePostName` component is rendered that allows us to edit the name of the post.

```tsx title="src/features/posts/PostDetail.tsx"
```tsx no-transpile title="src/features/posts/PostDetail.tsx"
export const PostDetail = () => {
const { id } = useParams<{ id: any }>()

Expand Down
38 changes: 19 additions & 19 deletions docs/rtk-query/usage/pagination.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,35 @@ export const { useListPostsQuery } = api

### Trigger the next page by incrementing the `page` state variable

```tsx title="src/features/posts/PostsManager.tsx"
```tsx no-transpile title="src/features/posts/PostsManager.tsx"
const PostList = () => {
const [page, setPage] = useState(1);
const { data: posts, isLoading, isFetching } = useListPostsQuery(page);
const [page, setPage] = useState(1)
const { data: posts, isLoading, isFetching } = useListPostsQuery(page)

if (isLoading) {
return <div>Loading</div>;
return <div>Loading</div>
}

if (!posts?.data) {
return <div>No posts :(</div>;
return <div>No posts :(</div>
}

return (
<div>
{posts.data.map(({ id, title, status }) => (
<div key={id}>{title} - {status}</div>
))}
<button onClick={() => setPage(page - 1)} isLoading={isFetching}>
Previous
</button>
<button
onClick={() => setPage(page + 1)}
isLoading={isFetching}
>
Next
</button>
{posts.data.map(({ id, title, status }) => (
<div key={id}>
{title} - {status}
</div>
))}
<button onClick={() => setPage(page - 1)} isLoading={isFetching}>
Previous
</button>
<button onClick={() => setPage(page + 1)} isLoading={isFetching}>
Next
</button>
</div>
);
};
)
}
```

### Automated Re-fetching of Paginated Queries
Expand Down Expand Up @@ -149,6 +148,7 @@ export const postApi = createApi({
}),
})
```

## General Pagination Example

In the following example, you'll see `Loading` on the initial query, but then as you move forward we'll use the next/previous buttons as a _fetching_ indicator while any non-cached query is performed. When you go back, the cached data will be served instantaneously.
Expand Down
2 changes: 1 addition & 1 deletion docs/rtk-query/usage/polling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description: 'RTK Query > Usage > Polling: re-fetching data on a timer'

Polling gives you the ability to have a 'real-time' effect by causing a query to run at a specified interval. To enable polling for a query, pass a `pollingInterval` to the `useQuery` hook or action creator with an interval in milliseconds:

```tsx title="src/Pokemon.tsx" no-transpile
```tsx no-transpile title="src/Pokemon.tsx" no-transpile
import * as React from 'react'
import { useGetPokemonByNameQuery } from './services/pokemon'

Expand Down
2 changes: 1 addition & 1 deletion docs/rtk-query/usage/prefetching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ You can specify these prefetch options when declaring the hook or at the call si
- **Assuming** you have a `useQuery` hook in the tree that is subscribed to the same query that you are prefetching:
- `useQuery` will return `{isLoading: false, isFetching: true, ...rest`}

```tsx title="usePrefetch Example"
```tsx no-transpile title="usePrefetch Example"
function User() {
const prefetchUser = usePrefetch('getUser')

Expand Down
16 changes: 10 additions & 6 deletions docs/rtk-query/usage/queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ const api = createApi({
// Pick out data and prevent nested properties in a hook or selector
transformResponse: (response: { data: Post }, meta, arg) => response.data,
// Pick out errors and prevent nested properties in a hook or selector
transformErrorResponse: (response: { status: string | number }, meta, arg) => response.status,
transformErrorResponse: (
response: { status: string | number },
meta,
arg
) => response.status,
providesTags: (result, error, id) => [{ type: 'Post', id }],
// The 2nd parameter is the destructured `QueryLifecycleApi`
async onQueryStarted(
Expand Down Expand Up @@ -158,7 +162,7 @@ In most cases, you will probably read `data` and either `isLoading` or `isFetchi

Here is an example of a `PostDetail` component:

```tsx title="Example"
```tsx no-transpile title="Example"
export const PostDetail = ({ id }: { id: string }) => {
const {
data: post,
Expand Down Expand Up @@ -199,7 +203,7 @@ For query endpoints, RTK Query maintains a semantic distinction between `isLoadi

This distinction allows for greater control when handling UI behavior. For example, `isLoading` can be used to display a skeleton while loading for the first time, while `isFetching` can be used to grey out old data when changing from page 1 to page 2 or when data is invalidated and re-fetched.

```tsx title="Managing UI behavior with Query Loading States"
```tsx no-transpile title="Managing UI behavior with Query Loading States"
import { Skeleton } from './Skeleton'
import { useGetPostsQuery } from './api'

Expand Down Expand Up @@ -236,7 +240,7 @@ shown. If posts for the current user have previously been fetched, and are re-fe
result of a mutation), the UI will show the previous data, but will grey out the data. If the user
changes, it will instead show the skeleton again as opposed to greying out data for the previous user.

```tsx title="Managing UI behavior with currentData"
```tsx no-transpile title="Managing UI behavior with currentData"
import { Skeleton } from './Skeleton'
import { useGetPostsByUserQuery } from './api'

Expand Down Expand Up @@ -274,7 +278,7 @@ Sometimes you may have a parent component that is subscribed to a query, and the

`selectFromResult` allows you to get a specific segment from a query result in a performant manner. When using this feature, the component will not rerender unless the underlying data of the selected item has changed. If the selected item is one element in a larger collection, it will disregard changes to elements in the same collection.

```tsx title="Using selectFromResult to extract a single result"
```tsx no-transpile title="Using selectFromResult to extract a single result"
function PostsList() {
const { data: posts } = api.useGetPostsQuery()

Expand All @@ -301,7 +305,7 @@ function PostById({ id }: { id: number }) {

Note that a shallow equality check is performed on the overall return value of `selectFromResult` to determine whether to force a rerender. i.e. it will trigger a rerender if any of the returned object values change reference. If a new array/object is created and used as a return value within the callback, it will hinder the performance benefits due to being identified as a new item each time the callback is run. When intentionally providing an empty array/object, in order to avoid re-creating it each time the callback runs, you can declare an empty array/object outside of the component in order to maintain a stable reference.

```tsx title="Using selectFromResult with a stable empty array"
```tsx no-transpile title="Using selectFromResult with a stable empty array"
// An array declared here will maintain a stable reference rather than be re-created again
const emptyArray: Post[] = []

Expand Down
Loading