React Hooks - How to avoid redeclaring functions on every render
Asked Answered
M

2

13

On a react class I would write something like this

class Myclass extends React.Component {
  handleUpdate = info => {
    //do the update
  }

  render() {
    return (
      <SomeMarkup>
        <SomeComponent onUpdate={this.handleUpdate} />
      </SomeMarkup>
    )
  }
}

If using a function I could just write the following

function MyFunction() {
  function handleUpdate(info) {
    // do the update
  }
  return (
    <SomeMarkup>
      <SomeComponent onUpdate={handleUpdate} />
    </SomeMarkup>
  )
}

...but with that I'd be redeclaring a function on every render. Is there any sort of trick that would memoize the handler function between renders? Or should I just move the handler out of the render scope? (Moving it out of the render scope requires me that I explicitly pass more parameters since I wont directly have access to the function scope.)

Mirabel answered 28/2, 2019 at 22:3 Comment(5)
Use a arrow function i heard its better for the memoryJazmin
arrow function only changes the scope of this, which is irrelevant for "non-classes"Mirabel
You are right, arrow functions are good for not binding every time. Back to your question, the only way to not recreate it every time is to pass it as a prop. It will use the function but not recreate it. That is the only way.Jazmin
is there a strong need here to avoid redeclaring the functions? any performance issue that's cropping up?Undo
performance issues related to big renders can easily show up when dealing with things like big controlled forms, where every keystroke may trigger 1 (or more) rerenders.Mirabel
N
8

This is exactly the scenario that useCallback is for. The function still gets declared every time with useCallback, but the function returned is memoized so that if it is passed as a property to children, the children will receive a consistent function unless it has to change due to dependencies changing.

Please see my recent related answer here that demonstrates in detail how useCallback works: Trouble with simple example of React Hooks useCallback

Here's another related answer: React Hooks useCallback causes child to re-render

Nabob answered 1/3, 2019 at 1:39 Comment(1)
thats me 5 years later. So basically the deal is that react mostly considers redeclaring functions negligible CPU. Memoizing is mostly for keeping references which may be compared on dependency arrays or React.memo components.Mirabel
I
-1
const UserList = ({ user, deleteUser }) => {
  return (
    <div className='user'>
      <div className='user-details'> {user}</div>
      ....
      <hr />
      <button onClick={() => deleteUser(user)}>Delete User</button>
    </div>
  )
}

const Users = () => {
  const [users, setUser] = useState([1, 2, 4, 5, 6]);
  const [count, setCount] = useState(0);

  const onHandleMouseLeave = () => {
    setCount(count => count + 1)
  }
  console.log("Mouse was entered no of time: ",count)

  const deleteUser = useCallback((id) => {
    const usersToBeUpdate = users.filter(user => user !== id);
    setUser([...usersToBeUpdate])
  }, [])
  return (
    <div>
      Users
      <div className='list-user' onMouseLeave={onHandleMouseLeave}>
        {users.map((user, i) =>
          <UserList user={user} deleteUser={deleteUser} />
        )}
      </div>
    </div>
  )
}
Intuitive answered 14/7 at 8:29 Comment(1)
you must use the react-hooks eslint package, which would point to a bug in your useCallback callMirabel

© 2022 - 2024 — McMap. All rights reserved.