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

使用useSWR点击触发请求遇两类错误:Hook合规性及渲染报错求助

问题修复方案

错误1:useSWR调用位置不符合Hook规则

原因

React Hooks(包括useSWR)必须在React函数组件的顶层或自定义Hook的顶层调用,不能放在普通函数(比如你提到的fetchUsers)、条件判断、循环或嵌套函数里。你的代码里useSWR被放在了非组件/非Hook的函数中,违反了Hook规则。

修复

将useState和useSWR移到React函数组件的顶层,确保它们在组件渲染时直接执行,而非嵌套在其他函数内。示例代码如下:

import { useState } from 'react';
import useSWR from 'swr';
import axios from 'axios';
import { Box, Button, Typography } from '@mui/material';

// React函数组件
function UserPortal() {
  // Hooks必须放在组件顶层
  const [shouldFetch, setShouldFetch] = useState(false);
  const fetcher = (url) => axios.get(url).then((res) => res.data);
  // 通过shouldFetch控制请求触发,符合Hook规则
  const { data, error, isLoading } = useSWR(shouldFetch ? "http://localhost:5000/users" : null, fetcher);

  // 点击事件处理函数
  const handleFetch = () => {
    setShouldFetch(true);
  };

  return (
    <div>
      <Box>
        <Button onClick={handleFetch}>View User</Button>
      </Box>

      {/* 修正后的渲染逻辑 */}
      <Typography>
        {!shouldFetch ? 'Students Portal' : (
          isLoading ? 'Loading...' : (
            error ? 'Failed to load users' : (
              <div>
                {data.name.map(user => (
                  <div key={user.id}>
                    ID: {user.id}, Age: {user.age}
                  </div>
                ))}
              </div>
            )
          )
        )}
      </Typography>
    </div>
  );
}

export default UserPortal;

错误2:Cannot read properties of undefined (reading 'name')

原因

  1. 当shouldFetch变为true后,SWR发起请求但数据尚未返回时,data处于undefined状态,直接访问data.name会触发报错。
  2. 按钮点击事件语法错误:onClick= setShouldFetch(true)会在组件渲染时立即执行状态变更,而非点击时触发,导致页面初始化就尝试访问未加载的data。

修复

  1. 修正按钮点击事件:将onClick= setShouldFetch(true)改为onClick={() => setShouldFetch(true)},确保仅在点击时触发状态更新。
  2. 处理请求状态:
    • 用SWR返回的isLoading判断是否处于加载状态,显示加载提示。
    • 用error判断请求是否失败,显示错误信息。
    • 必须先判断data是否存在,再访问其属性(或使用可选链data?.name),避免访问undefined的属性。
    • 接口返回的name是数组,需遍历渲染每个用户的具体信息,而非直接渲染数组本身。

若需要每次点击都重新发起请求,可将shouldFetch替换为时间戳变量,确保每次点击都生成新的请求key:

const [fetchKey, setFetchKey] = useState(null);
const handleFetch = () => {
  setFetchKey(Date.now());
};
const { data, error, isLoading } = useSWR(fetchKey ? "http://localhost:5000/users" : null, fetcher);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:35:20