React useEffect依赖缺失警告与无限循环问题求助
问题解决:React useEffect依赖警告与无限循环问题
问题描述
我编写了一个过滤函数,借助state变量data、dataCopy和searchValue实现数据过滤。当前遇到的问题是:如果不将data加入useEffect的依赖数组,React会抛出“React Hook useEffect has a missing dependency: 'data'”的警告;但如果将data加入依赖数组,又会因useEffect内部修改了data状态而触发无限循环。
核心问题分析
当前写法错误地用useEffect处理过滤逻辑,且在useEffect内修改data状态——这会形成依赖循环:修改data触发useEffect重新执行,useEffect又再次修改data,最终导致无限循环。
实际上,过滤操作属于纯计算逻辑,完全不需要依赖useEffect触发,直接基于原始数据dataCopy和搜索条件searchValue实时计算即可。
解决方案
步骤1:移除处理搜索的useEffect
删掉用于触发过滤的useEffect,避免依赖循环和不必要的状态更新。
步骤2:将过滤后的数据改为计算值(用useMemo优化性能)
保留dataCopy作为原始数据的唯一存储,过滤后的数据通过dataCopy和searchValue实时计算,无需单独存为state。如果数据量较大,用useMemo缓存计算结果,避免重复渲染损耗性能。
修改后的完整代码
import React, { useEffect, useState, useMemo } from 'react' import Header from '../Components/Header/Header' import Home from '../Components/Home/Home' import "./Layout.css" import Spinner from '../Components/Spinner/Spinner' import axios from 'axios' // 补全原代码遗漏的axios导入 function Layout() { // 原始数据与加载状态 const [dataCopy, setDataCopy] = useState([]) const [spinner, setSpinner] = useState(true) // 补全原代码遗漏的spinner状态 // 搜索输入状态 const [searchValue, setSearchValue] = useState("") // 更新搜索值 const changeSearchValue = (value) => { setSearchValue(value) } // 计算并缓存过滤后的数据 const filteredData = useMemo(() => { if (searchValue === "") { return dataCopy } return dataCopy.filter(item => !isNaN(searchValue) ? item.expected_annually_bill_amount.toString().includes(searchValue) : item.dmo_content.Ausgrid.toString().toLowerCase().includes(searchValue.toLowerCase()) ) }, [searchValue, dataCopy]) // API请求获取原始数据 useEffect(() => { axios.post(`${process.env.REACT_APP_BASE_URL}`, { data: "" }, { headers: { 'Api-key': `${process.env.REACT_APP_API_KEY}`, }, }) .then((response) => response.data.data.token) .then((tokenIs) => { return axios.post(`${process.env.REACT_APP_DATA_URL}`, { "session_id": `${process.env.REACT_APP_SESSION_ID}` }, { headers: { 'Api-key': `${process.env.REACT_APP_API_KEY}`, 'Auth-token': tokenIs, }, }) }) .then((response) => { setDataCopy(response.data.data.electricity) setSpinner(false) }) .catch((err) => { setSpinner(false) alert(err) }) }, []) return ( <> {spinner ? <Spinner /> : null} <div className='layout'> <Header changeSearchValue={changeSearchValue} searchValue={searchValue} /> <Home data={filteredData} /> </div> </> ) } export default Layout
额外说明
- 补全了原代码遗漏的
axios导入和spinner状态定义。 - 用
useMemo包裹过滤逻辑,仅在searchValue或dataCopy变化时重新计算,优化渲染性能。 - 这种写法彻底消除了useEffect的依赖问题,逻辑更清晰:原始数据仅在API请求时更新,过滤后的数据是纯计算结果。
内容的提问来源于stack exchange,提问作者Sharanjeet Singh
相关产品推荐
相关产品推荐

