- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 React 的新手,所以这可能很容易实现,但即使我做了一些研究,我自己也无法弄清楚。如果这太愚蠢了,请原谅我。
我正在使用Inertia.js使用 Laravel(后端)和 React(前端)适配器。如果您不了解惯性,它基本上是:
Inertia.js lets you quickly build modern single-page React, Vue andSvelte apps using classic server-side routing and controllers.
我正在做一个简单的登录页面,其中有一个表单,提交后将执行 POST 请求来加载下一页。它似乎工作正常,但在其他页面中控制台显示以下警告:
Warning: Can't perform a React state update on an unmounted component.This is a no-op, but it indicates a memory leak in your application.To fix, cancel all subscriptions and asynchronous tasks in a useEffectcleanup function.
in login (created by Inertia)
相关代码(我对其进行了简化以避免不相关的行):
import React, { useEffect, useState } from 'react'
import Layout from "../../Layouts/Auth";
{/** other imports */}
const login = (props) => {
const { errors } = usePage();
const [values, setValues] = useState({email: '', password: '',});
const [loading, setLoading] = useState(false);
function handleSubmit(e) {
e.preventDefault();
setLoading(true);
Inertia.post(window.route('login.attempt'), values)
.then(() => {
setLoading(false); // Warning : memory leaks during the state update on the unmounted component <--------
})
}
return (
<Layout title="Access to the system">
<div>
<form action={handleSubmit}>
{/*the login form*/}
<button type="submit">Access</button>
</form>
</div>
</Layout>
);
};
export default login;
现在,我知道我必须执行清理功能,因为请求的 promise 是生成此警告的原因。我知道我应该使用 useEffect
但我不知道如何在这种情况下应用它。我见过值更改时的示例,但是如何在此类调用中执行此操作?
根据要求,该组件的完整代码:
import React, { useState } from 'react'
import Layout from "../../Layouts/Auth";
import { usePage } from '@inertiajs/inertia-react'
import { Inertia } from "@inertiajs/inertia";
import LoadingButton from "../../Shared/LoadingButton";
const login = (props) => {
const { errors } = usePage();
const [values, setValues] = useState({email: '', password: '',});
const [loading, setLoading] = useState(false);
function handleChange(e) {
const key = e.target.id;
const value = e.target.value;
setValues(values => ({
...values,
[key]: value,
}))
}
function handleSubmit(e) {
e.preventDefault();
setLoading(true);
Inertia.post(window.route('login.attempt'), values)
.then(() => {
setLoading(false);
})
}
return (
<Layout title="Inicia sesión">
<div className="w-full flex items-center justify-center">
<div className="w-full max-w-5xl flex justify-center items-start z-10 font-sans text-sm">
<div className="w-2/3 text-white mt-6 mr-16">
<div className="h-16 mb-2 flex items-center">
<span className="uppercase font-bold ml-3 text-lg hidden xl:block">
Optima spark
</span>
</div>
<h1 className="text-5xl leading-tight pb-4">
Vuelve inteligente tus operaciones
</h1>
<p className="text-lg">
Recoge data de tus instalaciones de forma automatizada; accede a información histórica y en tiempo real
para que puedas analizar y tomar mejores decisiones para tu negocio.
</p>
<button type="submit" className="bg-yellow-600 w-40 hover:bg-blue-dark text-white font-semibold py-2 px-4 rounded mt-8 shadow-md">
Más información
</button>
</div>
<div className="w-1/3 flex flex-col">
<div className="bg-white text-gray-700 shadow-md rounded rounded-lg px-8 pt-6 pb-8 mb-4 flex flex-col">
<div className="w-full rounded-lg h-16 flex items-center justify-center">
<span className="uppercase font-bold text-lg">Acceder</span>
</div>
<form onSubmit={handleSubmit} className={`relative ${loading ? 'invisible' : 'visible'}`}>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-semibold mb-2" htmlFor="email">
Email
</label>
<input
id="email"
type="text"
className=" appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 outline-none focus:border-1 focus:border-yellow-500"
placeholder="Introduce tu e-mail.."
name="email"
value={values.email}
onChange={handleChange}
/>
{errors.email && <p className="text-red-500 text-xs italic">{ errors.email[0] }</p>}
</div>
<div className="mb-6">
<label className="block text-gray-700 text-sm font-semibold mb-2" htmlFor="password">
Contraseña
</label>
<input
className=" appearance-none border border-red rounded w-full py-2 px-3 text-gray-700 mb-3 outline-none focus:border-1 focus:border-yellow-500"
id="password"
name="password"
type="password"
placeholder="*********"
value={values.password}
onChange={handleChange}
/>
{errors.password && <p className="text-red-500 text-xs italic">{ errors.password[0] }</p>}
</div>
<div className="flex flex-col items-start justify-between">
<LoadingButton loading={loading} label='Iniciar sesión' />
<a className="font-semibold text-sm text-blue hover:text-blue-700 mt-4"
href="#">
<u>Olvidé mi contraseña</u>
</a>
</div>
<div
className={`absolute top-0 left-0 right-0 bottom-0 flex items-center justify-center ${!loading ? 'invisible' : 'visible'}`}
>
<div className="lds-ellipsis">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</form>
</div>
<div className="w-full flex justify-center">
<a href="https://optimaee.com">
</a>
</div>
</div>
</div>
</div>
</Layout>
);
};
export default login;
最佳答案
因为是异步 Promise 调用,所以必须使用可变引用变量(带有 useRef)来检查已卸载的组件,以便下一步处理异步响应(避免内存泄漏):
Warning: Can't perform a React state update on an unmounted component.
在这种情况下您应该使用两个 React Hook:useRef
和 useEffect
。
例如,使用 useRef
时,可变变量 _isMounted
始终指向内存中的同一引用(不是局部变量)
useRef is the go-to hook if mutable variable is needed. Unlike localvariables, React makes sure same reference is returned during eachrender. If you want, it's the same with this.myVar in Class Component
示例:
const login = (props) => {
const _isMounted = useRef(true); // Initial value _isMounted = true
useEffect(() => {
return () => { // ComponentWillUnmount in Class Component
_isMounted.current = false;
}
}, []);
function handleSubmit(e) {
e.preventDefault();
setLoading(true);
ajaxCall = Inertia.post(window.route('login.attempt'), values)
.then(() => {
if (_isMounted.current) { // Check always mounted component
// continue treatment of AJAX response... ;
}
)
}
}
<小时/>
同时,让我向您解释一下这里使用的 React Hooks 的更多信息。另外,我还将比较功能组件(React >16.8)中的 React Hooks 与类组件中的 LifeCycle。
useEffect : Most side-effects happen inside the hook. Examples of side effects are : data fetching, setting up a subscription, and manually changing the DOM React components. The useEffect replaces a lot of LifeCycles in Class Component (componentDidMount, componentDidUpate, componentWillUnmount)
useEffect(fnc, [dependency1, dependency2, ...]); // dependencies array argument is optional
useEffect 的默认行为在第一次渲染后运行(如 ComponentDidMount),并且在每次更新渲染后运行(如果您没有依赖项)(如 ComponentDidUpdate) 。就像这样:useEffect(fnc);
为 useEffect 提供一系列依赖项将改变其生命周期。在此示例中:useEffect 将在第一次渲染后以及每次计数更改时调用一次
导出默认函数() {const [count, setCount] = useState(0);
useEffect(fnc, [count]);
}
如果您为依赖项放置一个空数组,则 useEffect 将仅在第一次渲染后运行一次(如 ComponentDidMount)。就像这样:useEffect(fnc, []);
为了防止资源泄漏,当钩子(Hook)的生命周期结束时,所有内容都必须被释放(如 ComponentWillUnmount)。例如,如果依赖项为空数组,则返回的函数将在组件卸载后调用。就像这样:
useEffect(() => {返回fnc_cleanUp;//fnc_cleanUp 将取消所有订阅和异步任务(例如:clearInterval)}, []);
useRef : returns a mutable ref object whose .current property isinitialized to the passed argument (initialValue). The returned objectwill persist for the full lifetime of the component.
示例:对于上面的问题,我们不能在这里使用局部变量,因为它会丢失并在每次更新渲染时重新启动。
const login = (props) => {
let _isMounted= true; // it isn't good because of a local variable, so the variable will be lost and re-defined on every update render
useEffect(() => {
return () => {
_isMounted = false; // not good
}
}, []);
// ...
}
因此,通过结合使用 useRef 和 useEffect,我们可以彻底清除内存泄漏。
<小时/>您可以阅读有关 React Hooks 的更多内容的好链接是:
[EN] https://medium.com/@sdolidze/the-iceberg-of-react-hooks-af0b588f43fb
关于javascript - 清理 React Hooks 中未安装组件的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59780268/
我需要为元素属性动态构建 XPath 查询,其中属性值由用户提供。我不确定如何清理或清理此值以防止 XPath 等同于 SQL 注入(inject)攻击。例如(在 PHP 中): xpath("//m
问题很简单:在使用 PHPmailer 类时我应该使用任何类型的清理吗? 我制作了使用 phpmailer 类发送电子邮件的简单发送邮件表单。目前我只使用“htmlspecialchars”进行清理(
你可以在python中创建一个在for循环退出时运行清理代码的迭代吗?就像是: from random import randint class Iterable: def __iter__(
假设我定期将数据插入 SQLite 数据库,然后清除前 50% 的数据,但我不清理。 我现在是否有类似文件前 50% 的清零页面之类的东西?如果我添加另一批数据,我是否正在填写那些清零的页面? 手册中
我有一堆 HTML 代码,我想在其中删除所有 HTML 标记。 我认为 Regex(正则表达式)可以做到这一点。通过搜索和替换,我将如何执行此操作? 我尝试了 ,我认为 * 是通配符,但显然不是。
我仍在学习 Haskell,我想知道是否有一种不太冗长的方法来使用 1 行代码来表达以下语句: map (\x -> (x, (if mod x 3 == 0 then "fizz" else "")
我需要怎么做才能正确清理/转义程序化SSH命令中输入的参数? 例如,路径参数- public boolean exists(String path) { try { Chann
这个问题已经有答案了: How to clear the canvas for redrawing (25 个回答) 已关闭10 个月前。 我目前正在尝试创建一个带有雨滴落下的 Canvas ,我唯一
我目前正在使用此过程来清理/过滤用户输入的评论 -> 这个是用来去掉斜线的……和 if (get_magic_quotes_gpc()) { function stripslashe
是否可以在 portal_setup 中删除旧的导入配置文件。 目前,我的网站上有许多可追溯到 2009 年的条目:: import-all-profile-Products.Archetypes_
假设我有多个指令,包括以下内容: ...template content... ...template content... 你如何销毁指令?通常我会在 jquery 中做一些我 $('#2').re
我正在开发一个可移植java应用程序,它可以在用户的PC(Windows XP)上动态生成一些文件。现在,我想要的是在java程序退出后删除这些临时文件。显然,java的文件删除机制是不可信的。即
我有一个 argv c 程序,它反转单词,并查看它是否是回文。我只是想清理输出并让它打印原始输入而不是相反的输入,但由于它是 argv,我似乎不知道该怎么做。 int main(int argc, c
我的网页上有一篇用 markdown 写的文章,我想在索引页上显示一份简短的简历。 问题是正文有markdown,我想在简历上显示纯文本。 例如: Article text: Hello people
在下面的代码片段中,可以做些什么来a)让编译器安静,b)清理交叉的指针困惑? extern struct tree *sintablein[sintablesize]; struct tree *(*
我试图弄清楚 WeakHashMap 在垃圾收集后如何清理。正如你们中许多人可能知道的那样,当 WeakHashMap 条目的键被垃圾回收时,它会自动删除。但是,例如,如果我做这样的事情: List>
我对构建的理解是,它只编译上次构建中编辑过的Java文件,而干净构建将删除所有类文件并重新编译所有文件。那么,当单独构建就足以满足我提供最新版本的类文件的需要时,干净构建的效用是什么? 最佳答案 有时
是否有任何简单的(内置的、附加的、开源的或商业的)在 Postgresql(主从)上进行复制,以便在复制时清理从属内部的数据以符合 PCI 合规性? ETL工具怎么样?它不一定是瞬时的……最多一个小时
我有一个将数据保存到 MySQL 数据库的网站 在将 HTML 插入 MySQL 或在我的网站上显示它时,我应该转义 HTML 吗? 理想情况下,我想将原始 HTML 输入到我的数据库中,并在每次从中
我知道我已经asked一个关于 sanitizer 和转义的问题,但我有一个问题没有得到回答。 好了,到此为止。如果我有一个 PHP 脚本并且我 GET用户输入和SELECT它来自 mySQL 数据库
我是一名优秀的程序员,十分优秀!