我的应用程序让用户输入一个查询,以向Pokemon API发出请求,并呈现响应数据。
如果用户输入了数据库中不存在的查询,它将触发错误边界和Try Again
按钮,通过重置查询状态从错误中恢复,并让用户重新提交不同的查询。这是预期行为。
但是,在我当前的设置中,当用户的查询没有任何匹配项时,控制台将显示GET https://pokeapi.co/api/v2/pokemon/foo 404
和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>
);
};
我认为问题来自于使用错误边界的方式。
如果我们查看反应错误边界的文档,我们会看到以下内容:
最简单的使用方法是将其包装在任何可能引发错误的组件上。这将处理该组件及其子代引发的错误。
在您的示例中,引发错误的组件是渲染ErrorBoundary
的组件。但为了使其工作,引发错误的组件应该是ErrorBoundary
的子级。
我创建了一个稍微不同的沙箱来说明这一点。https://codesandbox.io/s/jovial-poincare-06e6v