我正在使用钩子 useEffect 向我的服务器发出获取请求,并且不断收到此警告:
警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。
我明白这个警告的原因,但是我该如何清除它呢?我尝试过本文中建议的方法,但没有成功:https://dev.to/pallymore/clean-up-async-requests-in-useeffect-hooks-90h
这是我的代码:
import React, { useEffect, useState } from 'react';
import { Redirect, Route } from 'react-router-dom';
export default function ProtectedRoute({ component: Component, ...rest }) {
const [ user, setUser ] = useState('');
useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('http://localhost:5000/user', {
credentials: 'include'
});
const data = await response.json();
setUser(data.session.passport.user);
} catch (error) {
console.log(error);
}
}
fetchUser();
return () => …Run Code Online (Sandbox Code Playgroud) const [image, setImage] = useState({ preview: "", file: "" });
const handleChange = (e) => {
e.preventDefault();
if (e.target.files.length) {
setImage({
preview: URL.createObjectURL(e.target.files[0]),
file: e.target.files[0],
});
}
};
useEffect(() => {
const formData = new FormData();
formData.append("file", image.file);
console.log(formData);
}, [image]);
Run Code Online (Sandbox Code Playgroud)
上面的代码console.log(formData);返回空对象,无法在axios上发送文件
useEffect我在功能组件中使用反应钩子,并且想知道当您不指定依赖项时它的用途是什么。我知道文档声明它用于副作用,但我的问题是为什么这些副作用不能在功能组件内使用纯 JS 运行?作为一个非常基本的示例,我正在使用以下代码:
import {useEffect, useState} from 'react'
function Child () {
const [clickCount, updateCount] = useState(0)
console.log('Run outside of useEffect')
useEffect(()=>{
console.log("Run inside of useEffect")
})
return (
<button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
)
}
export default Child
Run Code Online (Sandbox Code Playgroud)
正如您所期望的那样,它基本上只是一个普通的 JS 函数,在每次由单击按钮引起的重新渲染时,console.log都会执行这两个函数。
我理解为什么您可能想要useEffect在如下情况下使用,您只想useEffect在某些特定更改时运行:
import {useEffect, useState} from 'react'
function Child () {
const [clickCount, updateCount] = useState(0)
console.log('Run outside of useEffect')
//this now only runs when `someVariable` changes
useEffect(()=>{ …Run Code Online (Sandbox Code Playgroud) 我有一个 useEffect
function Component () {
const facets = useSelector(getFacets)
useEffect(() => {
dispatch(search(facets, param2, param3))
}, [dispatch, facets, param2, param3])
//rest of component with return
}
Run Code Online (Sandbox Code Playgroud)
现在搜索实际上会更新facets
//Inside my slice
const search = (facets, param2, param3) => async(dispatch) => {
//do a fetch using param2 and param3
//fetch comes back with a facets object
//alter response facets object based on 'old' facets
dispatch(setFacets(newFacets)) // set the new facets
}
Run Code Online (Sandbox Code Playgroud)
问题是,当此 useEffect 运行时,重新渲染会导致const facets = useSelector(getFacets)加载新值... Linting …
如果我返回一个函数,useEffect我可以确定该函数将在组件卸载时运行。但 React 似乎在调用我的卸载函数之前擦除了本地状态。
考虑一下:
function Component () {
const [setting, setSetting] = useState(false)
useEffect(() => {
setSetting(true)
// This should be called when unmounting component
return () => {
console.log('Send setting to server before component is unmounted')
console.log(setting) // false (expecting setting to be true)
}
}, [])
return (
<p>Setting is: {setting ? 'true' : 'false'}</p>
)
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以确认预期的行为是应该擦除组件状态吗?而且,如果这是正确的行为,那么如何在卸载组件之前将当前组件状态发送到服务器?
为了提供一些上下文,我正在消除对服务器的发布请求,以避免每次用户更改设置时都会触发它。去抖动效果很好,但我需要一种在用户离开页面后触发请求的方法,因为排队的去抖动方法将不再从未安装的组件中触发。
debouncing reactjs use-effect use-state react-component-unmount
假设我有一个父组件,它呈现一个子组件,而子组件所做的就是保持某种状态,并在其自身状态发生变化时触发 onChange 处理程序。请参阅下面的代码或 CodeSandbox。
这段代码进入无限循环,我想摆脱这种行为。
可能的解决方案,但我不喜欢的解决方案:
1:我可以将所有状态放在父组件中,并用父组件控制子组件,但这并不是我真正想要的。在现实生活中,我的子组件不仅仅负责一个简单的计数器,而且我想从父组件中轻松使用它。子组件内部有复杂的行为,我想向父组件传达一些简单的更改。或者这在 React 中是绝对不能做的吗?(保持子级状态并触发父级状态更新的更改)我想说这不一定吗?
2:我还可以从handleInternalChange 处理程序中触发onChange 处理程序。而且,也不是我想要的。在现实生活中,我的子组件将从组件本身的几个不同位置进行更新,因此状态更改是观察和触发 onChange 父组件的最优雅的方式。
3:我可以省略 useEffect 依赖项数组中的 onChange 依赖项。不推荐这样做,React社区参考了这个解释。我理解,只是我觉得这种情况是例外?** 另外,我使用 CRA,它带有开箱即用的很棒的 linter 等,如果我从依赖项中删除 onChange 处理程序,linter 会抱怨它,而且我不喜欢开始制定自己的班轮规则。对于像我这样的简单用例,社区设置的 linter 应该可以正常工作。
我认为会发生什么 我认为会发生的是,父级被更新,然后重新渲染整个事物,并且不知何故, onChange 处理程序也被“更改”。据我所说,该函数实际上并没有改变,但 React 认为(或知道)它改变了,因此它在子组件中再次触发 useEffect 调用,然后无限循环诞生。
但是,就我而言, onChange 函数没有改变。那么为什么会触发 useEffect 调用呢?我怎样才能防止这种情况发生?
import React, { useState, useEffect } from "react";
const Comp = ({ onChange }) => {
const [internalState, setInternalState] = useState(0);
const handleChange = () => {
setInternalState(internalState + 1);
};
useEffect(() => { …Run Code Online (Sandbox Code Playgroud) 我正在创建一个 React 应用程序,其中有一种称为输入的状态,它正在从用户那里获取输入。我希望当我按下回车键时,警报应该显示正在设置状态的输入。但是,单击enter按键时,仅显示输入状态中设置的默认值。
但是,当我单击按钮(我创建该按钮是为了在警报中显示输入)时,警报中显示的输入是正确的。
请参阅下面的代码片段以供参考:
import React, { useEffect, useRef, useState } from 'react';
export default function ShowAlertExample() {
const [input, setInput ] = useState('1');
const handleInputChange = (e) => {
setInput(e.target.value);
}
const handleShowAlert = () => {
alert(input);
}
const checkKeyPress = (e) =>{
const { key, keyCode } = e;
console.log(key, keyCode)
if (keyCode === 13 ) {
alert(input);
}
}
useEffect(()=>{
window.addEventListener("keydown", checkKeyPress)
return ()=>{
window.removeEventListener("keydown", checkKeyPress)
}
}, [])
return (
<div>
<header …Run Code Online (Sandbox Code Playgroud) 我在 useEffect 挂钩中调用 get API,以在组件安装之前获取数据,但它多次调用 API,并且收到错误“To many API requests”。
const [total, setTotal] = useState(0);
const [message, setMessage] = useState('');
useEffect(() => {
covidApi.getData({url:'/totals'})
.then((response) => {
setTotal(response.data[0]);
setMessage('');
console.log(response.data);
})
.catch((error) => {
setMessage("No data found");
console.log(error);
})
});
Run Code Online (Sandbox Code Playgroud)
输出:

请让我知道这是在使用 useEffect 钩子渲染组件之前从 API 获取数据的最佳方式。
我从 Use Effect 挂钩(我对此相对较新)获取纬度和经度。我想返回使用效果挂钩之外的值,并将它们存储在变量中,甚至在需要时存储在状态中。我可以控制台记录值,但我是否只添加返回语句或以某种方式传递参数?我需要使用什么功能?我计划将纬度和经度数据传递到代码的其他部分,这就是为什么我尝试从 useEffect 挂钩检索它。
useEffect(() => {
if ("geolocation" in navigator) {
console.log("Available");
} else {
console.log("Not Available");
}
navigator.geolocation.getCurrentPosition(function (position) {
let lat = position.coords.latitude;
let long = position.coords.longitude;
console.log(lat);
console.log(long);
});
}, []);
Run Code Online (Sandbox Code Playgroud)
let newLat = lat?
let newLong = long?
Run Code Online (Sandbox Code Playgroud) 我正在使用 React-native,其中有一个名为的自定义 Hook,它使用useUser该方法从 AWS Amplify 获取用户信息Auth.getUserInfro,然后获取返回对象的一部分并用它设置一个状态变量。我还有另一个名为 hook 的useDataHook,它根据 userId 获取一些数据并将其设置为状态变量。
使用用户自定义挂钩:
import React, { useState, useEffect } from "react";
import { Auth } from "aws-amplify";
const getUserInfo = async () => {
try {
const userInfo = await Auth.currentUserInfo();
const userId = userInfo?.attributes?.sub;
return userId;
} catch (e) {
console.log("Failed to get the AuthUserId", e);
}
};
const useUserId = () => {
const [id, setId] = useState("");
useEffect(() => {
getUserInfo().then((userId) => { …Run Code Online (Sandbox Code Playgroud) reactjs ×10
use-effect ×10
react-hooks ×7
javascript ×5
use-state ×2
ajax ×1
arguments ×1
debouncing ×1
dom-events ×1
fetch ×1
react-native ×1
redux ×1