You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

useSWR组件状态未更新至fetcher Promise结果,isLoading状态异常求助

问题

  1. 组件状态无法更新为fetcher函数返回的Promise解析后的数据
  2. 初始状态未正确显示isLoading: true

代码实现

service.js

import axios from 'axios';
export const fetchNewsDetailsById = (newsID) => {
    console.log('args in fetch news ', newsID)
    const pr = axios.get('https://swapi.dev/api/people/1')
    .then(res => res.data)
    .then(res => {
        const X = res.data.filter(obj => obj.id == newsID)[0];
        console.log('api data ', X);
        //// THIS X I WANT IN MY COMPONENT
        return X;
    });
    console.log('my promise ', pr);
    return pr;
}

hooks.js

import useSWR from 'swr'
import { fetchNewsDetailsById } from './service';

export const useNewsDetailsBySlug =  (newSlug) => {
    const parts = newSlug.split("-");
    const newsId = parts[parts.length - 1];
    const { data, error, isLoading } = useSWR (
      ['news', newsId], fetchNewsDetailsById(newsId)
    );
    console.log(' news instance in the hook ', data);
    return {
      data,
      isLoading,
      isError: error
    }
  }

NewsDetails.jsx

import React, { useMemo } from 'react'
import { useParams } from 'react-router-dom';
import { formatDate } from '../../../helpers/dates';
import { useNewsDetailsBySlug } from './hooks';
const NewsDetails = () => {
  const { id: slug } = useParams();

  const reqObj = useNewsDetailsBySlug(slug);

  const { data: dataObj, isLoading, isError } = reqObj;

  console.log(reqObj)

  if (!isLoading && !dataObj && !isError) {
    return <h2>No State onlyyy !!</h2>;
  }
  if (isLoading) {
    return <h2>Loading...</h2>
  }
  if (isError) {
    return <h2>Oops !! something went wrong while fetching details of the news</h2>
  }

  return (
    <div>
        <h3>{dataObj.title}</h3>
    </div>
  )
}

export default NewsDetails;

当前状态与日志

当前组件状态始终为:

{data: undefined, isLoading: false, isError: undefined}

控制台日志:

args in fetch news  6
service.js:12 my promise  Promise 

hooks.js:10  news instance in the hook  undefined

component.jsx:12 {data: undefined, isLoading: false, isError: undefined}

service.js:9 api data -- Exact data in want to be in my component

问题排查与解决方案

1. useSWR fetcher参数传递错误

useSWR的第二个参数要求是函数,而非直接调用函数返回的Promise。你当前直接执行fetchNewsDetailsById(newsId),导致组件初始化时就触发请求,且useSWR无法监听Promise状态变化,因此不会更新data和isLoading。

修复后的hooks.js:

import useSWR from 'swr'
import { fetchNewsDetailsById } from './service';

export const useNewsDetailsBySlug =  (newSlug) => {
    const parts = newSlug.split("-");
    const newsId = parts[parts.length - 1];
    // 传递函数,useSWR会自动处理请求生命周期
    const { data, error, isLoading } = useSWR (
      ['news', newsId], () => fetchNewsDetailsById(newsId)
    );
    console.log(' news instance in the hook ', data);
    return {
      data,
      isLoading,
      isError: error
    }
  }

2. API响应数据处理错误

请求https://swapi.dev/api/people/1返回的结果中没有嵌套的data字段,你直接访问res.data.data会得到undefined,后续filter操作自然无法得到有效数据。另外,swapi的people接口返回数据没有id字段,需要从url字段提取。

修复后的service.js:

import axios from 'axios';
export const fetchNewsDetailsById = (newsID) => {
    console.log('args in fetch news ', newsID)
    return axios.get('https://swapi.dev/api/people/1')
    .then(res => {
        // swapi返回的res.data就是目标数据,无嵌套data字段
        console.log('api raw data ', res.data);
        // 从url中提取id:例如url为"https://swapi.dev/api/people/1/",提取最后一段数字
        const id = res.data.url.split('/').filter(Boolean).pop();
        // 匹配传入的newsID,匹配成功返回数据,否则返回null
        return id === newsID ? res.data : null;
    });
}

3. 组件逻辑简化

可以移除冗余的条件判断,让代码更清晰:

const NewsDetails = () => {
  const { id: slug } = useParams();
  const { data: dataObj, isLoading, isError } = useNewsDetailsBySlug(slug);

  if (isLoading) {
    return <h2>Loading...</h2>
  }
  if (isError || !dataObj) {
    return <h2>{isError ? 'Oops !! something went wrong' : 'No data found'}</h2>
  }

  return (
    <div>
        <h3>{dataObj.name}</h3> {/* swapi返回的是name字段,而非title */}
    </div>
  )
}

内容的提问来源于stack exchange,提问作者gkd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:33:16