首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >useFetch数据未定义

useFetch数据未定义
EN

Stack Overflow用户
提问于 2022-01-24 11:04:18
回答 1查看 493关注 0票数 1
代码语言:javascript
复制
const { response, setResponse } = useResponseState();

const handleNext = () => {
    if (
      response.currentResponse !== undefined &&
      response.responses!== undefined
    ) {
      if (response.currentResponse< response.responses.length) {
        setResponse({
          currentResponse: response.currentResponse + 1,
          responses: response.responses,
        });
      }
    }
  };

  const responseID= response.responses![response.currentResponse!].id ?? 0;
      const { data, error } = useFetch<ExampleType>(
        `${process.env.REACT_APP_API_ENDPOINT}example/${exampleID}`
      );

return error || !data ? (
    <>error</>
  ) : (
    <>success</>

有人能帮助我理解为什么当handleNext被调用时数据是未定义的。在返回的成功部分中,有一个按钮带有onclick,但我尝试只显示您需要看到的内容。有人能看到这里有什么不对劲吗?

ResponseState是一个上下文。

端点返回的内容如下:

代码语言:javascript
复制
{"id":1,"exampleProp2: "test"}

钩子:

代码语言:javascript
复制
import { useEffect, useReducer, useRef, useState } from 'react';
import State from './State';

type Cache<T> = { [url: string]: T };

// discriminated union type
type Action<T> =
  | { type: 'loading' }
  | { type: 'fetched'; payload: T }
  | { type: 'error'; payload: Error };

function useFetch<T = unknown>(url?: string, options?: RequestInit): State<T> {
  const cache = useRef<Cache<T>>({});

  // Used to prevent state update if the component is unmounted
  const cancelRequest = useRef<boolean>(false);

  const initialState: State<T> = {
    error: undefined,
    data: undefined,
  };

  // Keep state logic separated
  const fetchReducer = (state: State<T>, action: Action<T>): State<T> => {
    switch (action.type) {
      case 'loading':
        return { ...initialState };
      case 'fetched':
        return { ...initialState, data: action.payload };
      case 'error':
        return { ...initialState, error: action.payload };
      default:
        return state;
    }
  };

  const [state, dispatch] = useReducer(fetchReducer, initialState);

  useEffect(() => {
    // Do nothing if the url is not given
    if (!url) return;

    const fetchData = async () => {
      dispatch({ type: 'loading' });

      // If a cache exists for this url, return it
      if (cache.current[url]) {
        dispatch({ type: 'fetched', payload: cache.current[url] });
        return;
      }

      try {
        const response = await fetch(url, options);
        if (!response.ok) {
          throw new Error(response.statusText);
        }

        const data = (await response.json()) as T;
        cache.current[url] = data;
        if (cancelRequest.current) return;

        dispatch({ type: 'fetched', payload: data });
      } catch (error) {
        if (cancelRequest.current) return;

        dispatch({ type: 'error', payload: error as Error });
      }
    };

    void fetchData();

    // Use the cleanup function for avoiding a possibly...
    // ...state update after the component was unmounted
    return () => {
      cancelRequest.current = true;
    };
  }, [url]);

  return state;
}

export default useFetch;

这正是使用的钩子。这里还有什么不管用的吗?

EN

回答 1

Stack Overflow用户

发布于 2022-01-24 13:05:02

我取决于您正在调用的useFetch的API契约是什么(钩子是如何工作的,预期返回值是什么)。但是通常情况下,抓取是一种异步操作,是在后台完成的。数据在第一阶段可以是undefinednull,因为没有发送请求或没有收到响应。

假设钩子返回以下内容- { data, error, loading, requested }。返回值可以如下:

  1. 提取未发送:{ loading: false, requested: false } (在您的情况下不太可能)
  2. 已发送,未收到响应:{ loading: true, requested: true }
  3. 收到的答复:{ loading: false, requested: true, data: {} }
  4. 收到的故障响应:{ loading: false, requested: true, error: {} }

如您所见,只有一种状态可以预期数据是可用的。这只是一个理论上的阐述,因为您还没有指定足够的useFetch钩子。

例如,您可以使用来自使用-http的钩子。如果您检查了文档,那么您应该注意到,它们建议按照自己的值初始化数据,以避免undefined。在你的例子中,它应该是这样的:

代码语言:javascript
复制
  const url = `${process.env.REACT_APP_API_ENDPOINT}example/${exampleID}`
  const { data = {}, error, loading } = useFetch < ExampleType > (url);

  return loading ? (
    <>Loading...</>
  ) : error ? (
    <>Failure: ${JSON.stringify(error)}</>
  ) : (
    <>Success: ${JSON.stringify(data))</>
  )

您应该明确地检查您正在使用的useFetch<T>文档,它应该在这里编写。

定制钩更新

对于来自指定物品的钩子,您还应该查阅axios反应的文档。它清楚地指出,data存储在这样命名的属性中。这意味着,如果您在文章中复制钩子代码,那么它就无法工作。Promise.then的处理程序没有一部分使用该值:

代码语言:javascript
复制
//checking for multiple responses for more flexibility 
//with the url we send in.
res.data.content && setData(res.data.content);
res.content && setData(res.content);

为了正确访问响应数据,必须对其进行修复,例如:

代码语言:javascript
复制
// Give up the flexibility
setData(rest.?data)
// Keep some flexibility
// ... but you have to define data acquisition algorithm
// const data = res.content || rest.data
// setData(data)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70832816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档