0

我的应用程序让用户输入查询以向 Pokemon API 发出请求,并呈现响应数据。

如果用户输入了数据库中不存在的查询,它将触发错误边界和一个Try Again按钮,通过重置查询状态并让用户重新提交不同的查询来从错误中恢复。这是预期的行为。

但是,使用我当前的设置,当用户的查询没有任何匹配项时,控制台将显示GET https://pokeapi.co/api/v2/pokemon/foo 404and Uncaught (in promise) Error: Request failed with status code 404。但是,用户没有看到此错误。没有什么可以告诉用户他们的查询没有任何匹配项。我的目标是获得更明确的用户体验,告诉用户他们提交的请求没有任何匹配项,然后单击Try Again按钮重置输入并提交新查询。我相信,这就是错误边界应该做的。

我正在使用以下库:React Query, React Hook Form, React Error Boundary. 有人建议我使用 React Query 的onError回调来记录错误并设置属性useErrorBoundary: true。仍然没有运气。

这是一个演示预期行为的工作示例。https://epic-react-exercises.vercel.app/react/hooks/3

这是我的尝试。请让我知道如何解决这个问题。https://codesandbox.io/s/pokedex-5j1jf

const ErrorFallback = ({ error, resetErrorBoundary }) => {
  return (
    <div role="alert">
      <p>Something went wrong:</p>
      <pre style={{ color: "red" }}>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
      <p>This error was caught by the error boundary!</p>
    </div>
  );
};

const searchSchema = yup.object().shape({
  pokemonName: yup.string().required()
});

const App = () => {
  const [query, setQuery] = useState("");
  const [pokemonCharacter, setPokemonCharacter] = useState({});
  const { register, handleSubmit, watch, errors } = useForm({
    resolver: yupResolver(searchSchema)
  });

  const handlePokemonFetch = () => {
    return axios(`https://pokeapi.co/api/v2/pokemon/${query}`).then((res) => {
      setPokemonCharacter(res.data);
    });
  };

  const { loading, error } = useQuery("pokemon", handlePokemonFetch, {
    refetchOnWindowFocus: false,
    enabled: false,
    useErrorBoundary: true,
    onError: (error) => console.log(error)
  });

  console.log(watch(pokemonCharacter));

  return (
    <div>
      <div>
                <form onSubmit={handleSubmit(handlePokemonFetch)}>
                    <label htmlFor="Pokemon">Pokémon Character</label>
                    <input
                        type="text"
                        name="pokemonName"
                        ref={register}
                        onChange={(event) => setQuery(event.target.value)}
                    />
                    {errors.pokemonName && <span>This field is required</span>}
                    {error && <p>Error occurred: {error.message}</p>}
                    <button type="submit">Search Pokémon</button>
                </form>
      </div>
            <ErrorBoundary
        FallbackComponent={ErrorFallback}
        onReset={() => {
          setQuery("");
        }}
        resetKeys={[query]}
      >
        <div>
          {loading && <p>Loading...</p>}
          <PokemonInfo pokemonCharacter={pokemonCharacter} />
        </div>
      </ErrorBoundary>
            <ReactQueryDevtools initialIsOpen={true} />
    </div>
  );
};
4

1 回答 1

1

我认为问题出在您使用错误边界的方式上。

如果我们查看 react-error-boundary 的文档,我们会看到以下内容:

最简单的使用方法是将它包裹在任何可能引发错误的组件周围。这也将处理该组件及其后代抛出的错误。

在您的示例中,引发错误的组件是呈现ErrorBoundary. 但是为了让它工作,抛出错误的组件应该是ErrorBoundary.

我创建了一个稍微不同的沙箱来说明这一点。https://codesandbox.io/s/jovial-poincare-06e6v

于 2021-03-26T14:05:39.577 回答