useCallback

React useCallback Hook

React useCallback Hook

useCallback Hook

useCallback Hook keshga olinadigan (memoized) qayta ishlovchi funksiyani qaytaradi.

Keshga olishni hisoblashning qayta ishlanishi shart bo'lmagan qiymatlarni saqlash kabi tasavvur qilishingiz mumkin.

Bu resurs talab qiladigan funksiyalarni ajratishga yordam beradi, shunda ular har bir qayta chizishda avtomatik ravishda ishga tushmaydi.

useCallback Hook faqatgina uning bog'liqliklaridan biri yangilanganda ishga tushadi.

Bu samaradorlikni oshirishi mumkin.

useCallback va useMemo Hooks o'xshash. Asosiy farq shundaki, useMemo keshga olinadigan qiymatni qaytaradi, useCallback esa keshga olinadigan funksiyani qaytaradi. useMemo haqida ko'proq ma'lumot olish uchun useMemo bo'limiga qarang.

Muammo

useCallback ni ishlatishning bir sababi - komponentni qayta chizishdan oldin uning props o'zgargan bo'lsa, yangilanishini oldini olishdir.

Misolda, Todos komponenti todos o'zgarmasa qayta chizilmasligini o'ylashingiz mumkin:

Bu misol React.memo bo'limidagi misolga o'xshaydi.

Misol

index.js

import { useState } from 'react';
import ReactDOM from 'react-dom/client';
import Todos from './Todos';
 
const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
 
  const increment = () => {
    setCount((c) => c + 1);
  };
 
  const addTodo = () => {
    setTodos((t) => [...t, 'New Todo']);
  };
 
  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Todos.js

import { memo } from 'react';
 
const Todos = ({ todos, addTodo }) => {
  console.log('child render');
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};
 
export default memo(Todos);

Bu kodni ishga tushirib, count ni oshirish tugmasini bosing.

Siz Todos komponenti todos o'zgarmasa ham qayta chizilishini sezishingiz mumkin.

Nima uchun bu ishlamayapti? Biz memo ni ishlatmoqdamiz, shuning uchun Todos komponenti qayta chizilmasligi kerak, chunki todos holati yoki addTodo funksiyasi count oshirilganda o'zgarmaydi.

Bu "referensial tenglik" deb ataladigan narsadan kelib chiqadi.

Har safar komponent qayta chizilganda, uning funksiyalari qayta yaratiladi. Shuning uchun, addTodo funksiyasi haqiqatan ham o'zgargan bo'ladi.

Yechim

Buni tuzatish uchun useCallback Hook-dan foydalanib, funksiyani kerak bo'lmaguncha qayta yaratishni oldini olishimiz mumkin.

Todos komponentini keraksiz qayta chizishdan saqlash uchun useCallback Hook-dan foydalaning:

index.js

import { useState, useCallback } from 'react';
import ReactDOM from 'react-dom/client';
import Todos from './Todos';
 
const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
 
  const increment = () => {
    setCount((c) => c + 1);
  };
 
  const addTodo = useCallback(() => {
    setTodos((t) => [...t, 'New Todo']);
  }, [todos]);
 
  return (
    <>
      <Todos todos={todos} addTodo={addTodo} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
  );
};
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Todos.js

import { memo } from 'react';
 
const Todos = ({ todos, addTodo }) => {
  console.log('child render');
  return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
      <button onClick={addTodo}>Add Todo</button>
    </>
  );
};
 
export default memo(Todos);

Endi Todos komponenti faqat todos prop o'zgarganda qayta chiziladi.

Ushbu sahifada

GitHubda tahrirlash