Saya baru menggunakan React, jadi ini mungkin sangat sederhana untuk dicapai tetapi saya tidak bisa mengetahuinya sendiri meskipun saya sudah melakukan penelitian. Maafkan saya jika ini terlalu bodoh.
Konteks
Saya menggunakan Inertia.js dengan adapter Laravel (backend) dan React (front-end). Jika Anda tidak tahu Inersia, itu pada dasarnya:
Inertia.js memungkinkan Anda dengan cepat membangun aplikasi React, Vue, dan Svelte satu halaman modern menggunakan perutean dan pengontrol sisi-server klasik.
Isu
Saya sedang melakukan halaman login sederhana yang memiliki formulir yang ketika dikirimkan akan melakukan permintaan POST untuk memuat halaman berikutnya. Tampaknya berfungsi dengan baik tetapi di halaman lain konsol menunjukkan peringatan berikut:
Peringatan: Tidak dapat melakukan pembaruan status React pada komponen yang dilepas. Ini adalah no-op, tetapi ini menunjukkan kebocoran memori di aplikasi Anda. Untuk memperbaiki, batalkan semua langganan dan tugas tidak sinkron dalam fungsi pembersihan useEffect.
dalam login (dibuat oleh Inersia)
Kode terkait (Saya telah menyederhanakannya untuk menghindari baris yang tidak relevan):
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;
Sekarang, saya tahu bahwa saya harus melakukan fungsi pembersihan karena janji permintaan adalah apa yang menghasilkan peringatan ini. Saya tahu bahwa saya harus menggunakan useEffect
tetapi saya tidak tahu bagaimana menerapkannya dalam kasus ini. Saya telah melihat contoh ketika nilai berubah, tetapi bagaimana melakukannya dalam panggilan semacam ini?
Terima kasih sebelumnya.
Memperbarui
Seperti yang diminta, kode lengkap komponen ini:
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;
sumber
.then(() => {})
?Jawaban:
Karena itu adalah panggilan janji async, jadi Anda harus menggunakan variabel ref yang dapat diubah (dengan useRef) untuk memeriksa komponen yang sudah di-unmount untuk perawatan selanjutnya dari respons async (menghindari kebocoran memori):
Dua Kait Bereaksi yang harus Anda gunakan dalam kasus ini:
useRef
danuseEffect
.Dengan
useRef
, misalnya, variabel yang dapat berubah_isMounted
selalu menunjuk pada referensi yang sama dalam memori (bukan variabel lokal)Contoh:
Pada kesempatan yang sama, izinkan saya menjelaskan kepada Anda informasi lebih lanjut tentang React Hooks yang digunakan di sini. Juga, saya akan membandingkan React Hooks di Functional Component (versi React> 16.8) dengan LifeCycle in Class Component.
1) Perilaku default useEffect berjalan baik setelah render pertama (seperti ComponentDidMount) dan setelah setiap pembaruan render (seperti ComponentDidUpdate) jika Anda tidak memiliki dependensi. Seperti itu:
useEffect(fnc);
2) Memberikan berbagai dependensi untuk menggunakanEffect akan mengubah siklus hidupnya. Dalam contoh ini: useEffect akan dipanggil sekali setelah render pertama dan setiap kali perubahan dihitung
3) useEffect akan berjalan hanya sekali setelah render pertama (seperti ComponentDidMount) jika Anda meletakkan array kosong untuk dependensi. Seperti itu:
useEffect(fnc, []);
4) Untuk mencegah kebocoran sumber daya, semuanya harus dibuang ketika siklus hidup sebuah kait berakhir (seperti ComponentWillUnmount) . Sebagai contoh, dengan array ketergantungan yang kosong, fungsi yang dikembalikan akan dipanggil setelah komponen dilepas. Seperti itu:
Contoh: dengan pertanyaan di atas, kami tidak dapat menggunakan variabel lokal di sini karena itu akan hilang dan diinisiasi ulang pada setiap pembaruan render.
Jadi, dengan kombinasi useRef dan useEffect , kita dapat sepenuhnya membersihkan kebocoran memori.
Tautan baik yang dapat Anda baca lebih lanjut tentang React Hooks adalah:
[EN] https://medium.com/@sdolidze/the-iceberg-of-react-hooks-af0b588f43fb
[FR] https://blog.soat.fr/2019/11/react-hooks-par-lexemple/
sumber
Anda bisa menggunakan metode 'cancelActiveVisits' dari
Inertia
untuk membatalkan aktifvisit
dalamuseEffect
pembersihan kail.Jadi dengan panggilan ini yang aktif
visit
akan dibatalkan dan negara tidak akan diperbarui.jika
Inertia
permintaan dibatalkan maka akan mengembalikan respons kosong sehingga Anda harus menambahkan cek tambahan untuk menangani respons kosong. Tambahkan add catch block juga untuk menangani potensi kesalahan.Cara alternatif (solusi)
Anda dapat menggunakan
useRef
untuk menahan status komponen dan berdasarkan ini Anda dapat memperbaruistate
.Masalah:
Pertempuran itu muncul karena
handleSubmit
berusaha memperbarui keadaan komponen meskipun komponen telah dilepas dari dom.Larutan:
Menetapkan bendera untuk memegang status
component
, jikacomponent
inimounted
makaflag
nilai akantrue
dan jikacomponent
adalahunmounted
nilai flag akan palsu. Jadi berdasarkan ini kita dapat memperbaruistate
. Untuk status bendera dapat kita gunakanuseRef
untuk menyimpan referensi.Dan kemudian
useEffect
dalam fungsi pembersihan kita dapat mengatur benderafalse.
useEffecr fungsi pembersihan
Contoh:
Dan di handleSubmit kita dapat memeriksa apakah komponen sudah terpasang atau tidak dan memperbarui status berdasarkan ini.
Di lain mengatur
_componentStatus
ke nol untuk menghindari kebocoran memori.sumber
ajaxCall
dalamuseEffect
. dan lihat apa nilainyaundefined
. Saya telah menambahkannya tepat setelahreturn () => {