更新:好的,我误解了useDeferredValue,我认为它更像是一个去抖值,但事实并非如此,您可以将超时定义为显示旧结果的时间。
所以
const search = useDeferredValue(value, { timeoutMs: 10000 })
给了我想要的效果,只有它仍然显示警告权才知道。
原来的
我想搜索下面的结果,搜索结果应该根据文本字段的输入立即过滤。然后查询应该被去抖动并且旧的结果也应该在它花费少于例如 3000 毫秒时显示
我正在使用 React 和 Relay 实验中的新并发模式。我使用了新的 useDeferredValue,记录在此页面上:https ://reactjs.org/docs/concurrent-mode-reference.html#usetransition
但我收到了这个警告:
Warning: Asynchronous triggered a user-blocking update that suspended.
The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes.
Refer to the documentation for useTransition to learn how to implement this pattern
我没有得到这个,因为它有效,但它仍然给我一个警告。
我的代码:
import React, {
Suspense,
useState,
// @ts-ignore - useDeferredValue does not exist yet in types
useDeferredValue,
// @ts-ignore - useDeferredValue does not exist yet in types
// useTransition,
useCallback,
ChangeEvent,
} from 'react'
import TextField from '@material-ui/core/TextField'
import LinearProgress from '@material-ui/core/LinearProgress'
import { graphql } from 'babel-plugin-relay/macro'
import { useLazyLoadQuery } from 'react-relay/hooks'
import {
FlowBlockFinderQuery,
FlowBlockFinderQueryResponse,
} from '../__generated__/FlowBlockFinderQuery.graphql'
import ErrorBoundaryWithRetry from '../helpers/ErrorBoundaryWithRetry'
interface RenderFuncProps {
search: string
filterSearch: string
}
function QueryResults({ search, filterSearch }: RenderFuncProps) {
const { blocks }: FlowBlockFinderQueryResponse = useLazyLoadQuery<
FlowBlockFinderQuery
>(
graphql`
query FlowBlockFinderQuery($search: String) {
blocks(search: $search) {
id
title
description
slug
blockType
}
}
`,
{ search },
{ fetchPolicy: 'store-or-network' }
)
return (
<div>
{blocks
.filter(
block =>
!filterSearch ||
block.title.toLowerCase().includes(filterSearch.toLowerCase())
)
.map(block => (
<div key={block.id} style={{ fontSize: 19 }}>
{block.title}
</div>
))}
</div>
)
}
function Results({ search, filterSearch }: RenderFuncProps) {
return (
<>
Zoekterm: {filterSearch}
<ErrorBoundaryWithRetry
fallback={({ error }) => <div>Er is iets foutgegaan</div>}
>
<Suspense fallback={<LinearProgress />}>
<QueryResults search={search} filterSearch={filterSearch} />
</Suspense>
</ErrorBoundaryWithRetry>
</>
)
}
export default function Asynchronous() {
const [value, setValue] = useState('')
// const [search, setSearch] = useState('')
const search = useDeferredValue(value, { timeoutMs: 3000 })
// const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG)
const onInputChange = useCallback(
(event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
// startTransition(() => {
setValue(event.currentTarget.value)
// })
},
[setValue]
)
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<TextField
label="Nieuw of bestaand blok"
fullWidth
variant="outlined"
value={value}
onChange={onInputChange}
/>
<br />
<Results search={search} filterSearch={value} />
</div>
)
}