{name}-{ isSelected&&"Selected"});});"> Can I use React.useCallback inside another React.useCallback?-PHP Chinese Network Q&A
Can I use React.useCallback inside another React.useCallback?
P粉153503989
P粉153503989 2023-09-01 14:55:58
0
1
479

有一个渲染用户卡片的组件

import React from "react"; const User = React.memo(function({id, name, isSelected, ...other}) { return ( 
{name} - {isSelected && "Selected"}
); }); export default User;

以及渲染用户卡的父组件

import React from "react"; function Application() { const [users, setUsers] = React.useState([ {id: 1, name: "John Doe #1"}, {id: 2, name: "John Doe #2"}, {id: 3, name: "John Doe #3"} ]); const [selectedUserId, setSelectedUserId] = React.useState(null); return users.map((user) => { const isSelected = selectedUserId === user.id; return (  setSelectedUserId(user.id)} /> ); }); } export default Application;

任务是“选择用户后避免重新渲染其他用户卡”

我尝试使用 React.useCallback 钩子,这是我的第一个实现

import React from "react"; const User = React.memo(function({id, name, isSelected, ...other}) { return ( 
{name} - {isSelected && "Selected"}
); }); function Application() { const [users, setUsers] = React.useState([ {id: 1, name: "John Doe #1"}, {id: 2, name: "John Doe #2"}, {id: 3, name: "John Doe #3"} ]); const [selectedUserId, setSelectedUserId] = React.useState(null); const handleSelectUser = React.useCallback((userId) => () => { setSelectedUserId(userId); }, []); return users.map((user) => { const isSelected = selectedUserId === user.id; return ( ); }); } export default Application;

In this case, React.useCallback returns an anonymous function

with a new reference

Result: All user cards still re-render after each click

I decided to wrap this anonymous function in React.useCallback

import React from "react"; const User = React.memo(function({id, name, isSelected, ...other}) { return ( 
{name} - {isSelected && "Selected"}
); }); function Application() { const [users, setUsers] = React.useState([ {id: 1, name: "John Doe #1"}, {id: 2, name: "John Doe #2"}, {id: 3, name: "John Doe #3"} ]); const [selectedUserId, setSelectedUserId] = React.useState(null); const handleSelectUser = React.useCallback((userId) => { return React.useCallback(() => { setSelectedUserId(userId); }, []); }, []); return users.map((user) => { const isSelected = selectedUserId === user.id; return ( ); }); } export default Application;

The problem is solved, but there is still one question, did I do it right? The React team says: Don't call Hooks inside loops, conditionals, or nested functions What side effects will I get?

Note do not touch the usercomponent

P粉153503989
P粉153503989

reply all (1)
P粉810050669

Explain why a hook cannot be called from within a hook (and expect it to work consistently and reliably)

Why you can't call a hook inside a hook - go here for a super deep dive with more context than I need to provide in this answerhttps://overreacted.io/why-do-hooks -rely-on-call-order/

Your solution works because despite "breaking the rules" the order of calls to the hooks is always the same... until the user is added or removed from the state.

You can definitely use the solution you wrote. But what if you need tochange the number of users?


No, you cannot use hooks inside hooks. It might "work", but React is telling you that it doesn't work reliably and that you're doing it wrong. The hook must be called at the top level of the custom hook's top-level component.

Your direction is correct, but the solution to the problem is

  1. Use the parameters provided to the callback function as the source of the clicked element AND
  2. If you cannot modify the User component, you must provide some data on thedivelement to let you know which user element was clicked.

It looks like this:

function Application() { const [users, setUsers] = React.useState([ { id: 1, name: 'John Doe #1' }, { id: 2, name: 'John Doe #2' }, { id: 3, name: 'John Doe #3' }, ]); const [selectedUserId, setSelectedUserId] = React.useState(null); // this callback is referentially stable - it doesn't change between renders because it has no dependencies const handleSelectUser = React.useCallback((e) => { setSelectedUserId(+e.target.getAttribute('data-userid')); }, []); return users.map((user) => { const isSelected = selectedUserId === user.id; return (  ); }); }
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template
    About us Disclaimer Sitemap
    php.cn:Public welfare online PHP training,Help PHP learners grow quickly!