0

更新:好的,我误解了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>
  )
}
4

1 回答 1

0

React 文档“如果某些状态更新导致组件挂起,则该状态更新应包含在转换中”。您必须使异步请求挂起兼容并在 useTransition 中获取查询。

这是来自反应文档的示例

function handleChange(e) {
  const value = e.target.value;

  // Outside the transition (urgent)
  setQuery(value);

  startTransition(() => {
    // Inside the transition (may be delayed)
    setResource(fetchTranslation(value));
  });
 }

以及代码沙箱的链接

于 2019-12-07T06:14:15.193 回答