Bolehkah saya menggunakan React.useCallback di dalam React.useCallback yang lain?
P粉153503989
2023-09-01 14:55:58
<p>有一个渲染用户卡片的组件</p>
<p>
<pre class="brush:js;toolbar:false;">import React daripada "react";
const Pengguna = React.memo(fungsi({id, nama, isSelected, ...other}) {
kembali (
<div {...other}>
{name} - {isSelected && "Dipilih"}
</div>
);
});
eksport Pengguna lalai;</pre>
</p>
<p>以及渲染用户卡的父组件</p>
<p>
<pre class="brush:js;toolbar:false;">import React daripada "react";
fungsi Aplikasi() {
const [pengguna, setUsers] = React.useState([
{id: 1, nama: "John Doe #1"},
{id: 2, nama: "John Doe #2"},
{id: 3, nama: "John Doe #3"}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
kembalikan pengguna.peta((pengguna) => {
const isSelected = selectedUserId === user.id;
kembali (
<Pengguna
{...pengguna}
key={user.id}
isSelected={isSelected}
onClick={() => setSelectedUserId(user.id)}
/>
);
});
}
eksport lalai Aplikasi;</pre>
</p>
<p>任务是“选择用户后避免重新渲染其他用户卡”</p>
<p>我尝试使用 <kod>React.useCallback</code> 钩子,这是我的第一个实现</p>
<p>
<pre class="brush:js;toolbar:false;">import React daripada "react";
const Pengguna = React.memo(fungsi({id, nama, isSelected, ...other}) {
kembali (
<div {...other}>
{name} - {isSelected && "Dipilih"}
</div>
);
});
fungsi Aplikasi() {
const [pengguna, setUsers] = React.useState([
{id: 1, nama: "John Doe #1"},
{id: 2, nama: "John Doe #2"},
{id: 3, nama: "John Doe #3"}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
const handleSelectUser = React.useCallback((userId) => () => {
setSelectedUserId(userId);
}, []);
kembalikan pengguna.peta((pengguna) => {
const isSelected = selectedUserId === user.id;
kembali (
<Pengguna
{...pengguna}
key={user.id}
isSelected={isSelected}
onClick={handleSelectUser(user.id)}
/>
);
});
}
eksport lalai Aplikasi;</pre>
</p>
<p>Dalam kes ini, <code>React.useCallback</code> mengembalikan fungsi tanpa nama</p>
<p><strong>Hasil: Semua kad pengguna masih dipaparkan semula selepas setiap klik</strong></p>
<p>Saya memutuskan untuk membungkus fungsi tanpa nama ini dalam <code>React.useCallback</code></p>
<p>
<pre class="brush:js;toolbar:false;">import React daripada "react";
const Pengguna = React.memo(fungsi({id, nama, isSelected, ...other}) {
kembali (
<div {...other}>
{name} - {isSelected && "Selected"}
</div>
);
});
fungsi Aplikasi() {
const [pengguna, setUsers] = React.useState([
{id: 1, nama: "John Doe #1"},
{id: 2, nama: "John Doe #2"},
{id: 3, nama: "John Doe #3"}
]);
const [selectedUserId, setSelectedUserId] = React.useState(null);
const handleSelectUser = React.useCallback((userId) => {
kembalikan React.useCallback(() => {
setSelectedUserId(userId);
}, []);
}, []);
kembalikan pengguna.peta((pengguna) => {
const isSelected = selectedUserId === user.id;
kembali (
<Pengguna
{...pengguna}
key={user.id}
isSelected={isSelected}
onClick={handleSelectUser(user.id)}
/>
);
});
}
eksport lalai Aplikasi;</pre>
</p>
<p>Masalah sudah selesai, tetapi masih ada satu soalan, adakah saya melakukannya dengan betul? Pasukan React berkata: <em>Jangan panggil Hooks dalam gelung, bersyarat atau fungsi bersarang</em> </p>
<p>Perhatikan jangan sentuh <kod>pengguna</kod>komponen</p>
Terangkan mengapa cangkuk tidak boleh dipanggil dari dalam cangkuk (dan harapkan ia berfungsi secara konsisten dan boleh dipercayai)
Mengapa anda tidak boleh memanggil cangkuk di dalam cangkuk - pergi ke sini untuk menyelam yang sangat mendalam dengan lebih banyak konteks daripada yang perlu saya berikan dalam jawapan ini https://overreacted.io/why-do-hooks-rely-on -call-order/
Penyelesaian anda berfungsi kerana walaupun "melanggar peraturan" susunan panggilan ke cangkuk sentiasa sama...sehingga pengguna ditambah atau dialih keluar dari keadaan.
Anda pasti boleh menggunakan penyelesaian yang anda tulis. Tetapi bagaimana jika anda perlu menukar bilangan pengguna?
Tidak, anda tidak boleh menggunakan cangkuk di dalam cangkuk. Ia mungkin "berfungsi", tetapi React memberitahu anda bahawa ia tidak berfungsi dengan pasti dan anda melakukannya dengan salah. Cangkuk mesti dipanggil di peringkat atas komponen peringkat atas cangkuk tersuai.
Anda berada di arah yang betul, tetapi penyelesaian kepada masalah adalah
div
untuk memberitahu anda elemen pengguna yang telah diklik.Ia kelihatan seperti ini: