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

React应用点击编辑/添加按钮触发额外API调用问题求助

问题分析与解决方案

原因排查

你的Home组件中,API调用放在了空依赖数组的useEffect中,理论上只会在组件首次挂载时执行一次。但点击编辑/添加按钮后触发额外API调用,大概率是以下两种情况:

  • 组件重复挂载:当你通过navigate跳转到/addUser或/editUser/:id后返回Home页面时,Home组件会重新挂载,导致useEffect再次执行,触发API请求。
  • 无数据存在校验:即使Redux store中已有用户数据,每次组件挂载都会重复发起API请求并将数据重复dispatch到store中,放大了问题影响。

解决方案

方案1:通过Redux状态判断,避免重复请求

在useEffect中先检查Redux中是否已有用户数据,仅当数据为空时才发起API请求:

import React, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux'
import { removePerson, addPerson } from '../actions/Slice';

export default function Home() {
    const navigate = useNavigate();
    const dispatch = useDispatch();
    const people = useSelector(state => state.people);

    useEffect(() => {
        // 仅当store中无数据时才发起请求
        if (people.length === 0) {
            fetch("https://reqres.in/api/users?page=1")
                .then((response) => response.json())
                .then((totaldata) => {
                    const users = totaldata.data.map(user => ({
                        id: user.id,
                        first: user.first_name,
                        last: user.last_name,
                        email: user.email
                    }));
                    users.forEach(user => dispatch(addPerson(user)));
                })
                .catch((err) => {
                    console.log(err.message);
                });
        }
    }, [people, dispatch]); // 添加依赖,确保状态变化时能正确判断

    // 其余原有代码保持不变
}

方案2:使用useRef标记请求状态,确保仅执行一次

如果希望无论组件是否重新挂载,API都只请求一次,可以用useRef标记请求是否已完成:

import React, { useEffect, useRef } from 'react'
import { useNavigate } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux'
import { removePerson, addPerson } from '../actions/Slice';

export default function Home() {
    const navigate = useNavigate();
    const dispatch = useDispatch();
    const isApiFetched = useRef(false); // 标记是否已请求过API

    useEffect(() => {
        if (!isApiFetched.current) {
            fetch("https://reqres.in/api/users?page=1")
                .then((response) => response.json())
                .then((totaldata) => {
                    const users = totaldata.data.map(user => ({
                        id: user.id,
                        first: user.first_name,
                        last: user.last_name,
                        email: user.email
                    }));
                    users.forEach(user => dispatch(addPerson(user)));
                    isApiFetched.current = true; // 请求完成后标记为已执行
                })
                .catch((err) => {
                    console.log(err.message);
                });
        }
    }, [dispatch]);

    // 其余原有代码保持不变
}

额外优化建议

  • 列表项的key使用${pop.id}_${index}没必要,pop.id是唯一标识,直接用pop.id作为key即可,避免因索引变化导致不必要的组件重渲染:
    <tr key={pop.id}>
    
  • 可以把API请求逻辑封装到Redux的thunk action中,统一管理请求的loading、error状态,让组件逻辑更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:23:24