useState הוא React Hook המאפשר לך להוסיף משתנה state לרכיב שלך.

const [state, setState] = useState(initialState)

הפניה

useState(initialState)

התקשר ל-useState ברמה העליונה של הרכיב שלך כדי להכריז על משתנה state.

import { useState } from 'react';

function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos());
// ...

המוסכמה היא לתת שם למשתנים state כמו [something, setSomething] באמצעות הרס מערך.

ראה דוגמאות נוספות למטה.

פרמטרים

  • initialState: הערך שאתה רוצה שה-state יהיה בהתחלה. זה יכול להיות ערך מכל סוג, אבל יש התנהגות מיוחדת לפונקציות. טענה זו מתעלמת לאחר העיבוד הראשוני.
    • אם תעביר פונקציה בתור initialState, היא תטופל כאל פונקציית התחלה. זה צריך להיות טהור, לא צריך לקחת טיעונים, וצריך להחזיר ערך מכל סוג שהוא. React יקרא לפונקציית האתחול שלך בעת אתחול הרכיב, ויאחסן את ערך ההחזר שלו כ-state הראשוני. ראה דוגמה למטה.

מחזירה

useState מחזיר מערך עם שני ערכים בדיוק:

  1. ה-state הנוכחי. במהלך העיבוד הראשון, הוא יתאים ל-initialState שעברת.
  2. הפונקציה set המאפשרת לך לעדכן את ה-state לערך אחר ולהפעיל עיבוד מחדש.

אזהרות

  • useState הוא Hook, אז אתה יכול לקרוא לו רק ברמה העליונה של הרכיב שלך או Hooks משלך. אתה לא יכול לקרוא לזה בתוך לולאות או תנאים. אם אתה צריך את זה, חלץ רכיב חדש והעביר את ה-state לתוכו.
  • במצב קפדני, React יתקשר לפונקציית האתחול שלך פעמיים ​​כדי לעזור לך למצוא זיהומים מקריים. זוהי התנהגות לפיתוח בלבד ואינה משפיעה על הייצור. אם פונקציית האתחול שלך טהורה (כפי שהיא צריכה להיות), זה לא אמור להשפיע על ההתנהגות. התוצאה מאחת השיחות תתעלם.

פונקציות set, כמו setSomething(nextState)

הפונקציה set המוחזרת על ידי useState מאפשרת לך לעדכן את ה-state לערך אחר ולהפעיל עיבוד מחדש. אתה יכול להעביר את ה-state הבא ישירות, או פונקציה שמחשבת אותו מה-state הקודם:

const [name, setName] = useState('Edward');

function handleClick() {
setName('Taylor');
setAge(a => a + 1);
// ...

פרמטרים

  • nextState: הערך שאתה רוצה שה-state יהיה. זה יכול להיות ערך מכל סוג, אבל יש התנהגות מיוחדת לפונקציות.
    • אם תעביר פונקציה בתור nextState, היא תטופל כאל פונקציית עדכון. זה חייב להיות טהור, צריך לקחת את ה-state הממתין כארגומנט היחיד שלו, ועליו להחזיר את ה-state הבא. React ישים את פונקציית העדכון שלך בתור ותעבד מחדש את הרכיב שלך. במהלך העיבוד הבא, React יחשב את ה-state הבא על ידי החלת כל העדכונים בתור על ה-state הקודם. ראה דוגמה למטה.

מחזירה

לפונקציות set אין ערך החזרה.

אזהרות

  • הפונקציה set מעדכנת רק את המשתנה state עבור העיבוד הבא. אם תקרא את המשתנה state לאחר קריאה לפונקציה set, אתה עדיין תקבל את הערך הישן שהיה על המסך לפני השיחה שלך.

  • אם הערך החדש שתספק זהה ל-state הנוכחי, כפי שנקבע על ידי Object.is השוואה, React ידלג על עיבוד מחדש של הרכיב והילדים שלו. זוהי אופטימיזציה. למרות שבמקרים מסוימים ייתכן שReact יצטרך להשפיע על הקוד לפני שהקוד ישפיע.

  • React אצות state עדכונים. הוא מעדכן את המסך לאחר שכל מטפלי האירועים פעלו וקראו לפונקציות set שלהם. זה מונע רינדורים חוזרים מרובים במהלך אירוע בודד. במקרה הנדיר שאתה צריך לאלץ את React לעדכן את המסך מוקדם יותר, למשל כדי לגשת ל-DOM, אתה יכול use flushSync.

  • קריאה לפונקציה set במהלך העיבוד מותרת רק מתוך רכיב העיבוד הנוכחי. React ימחק את הפלט שלו וינסה מיד לעבד אותו שוב עם ה-state החדש. דפוס זה נדרש רק לעתים רחוקות, אך אתה יכול use אותו כדי לשמור מידע מהעיבודים הקודמים. ראה דוגמה למטה.

  • במצב קפדני, React תתקשר לפונקציית העדכון שלך פעמיים ​​כדי לעזור לך למצוא זיהומים מקריים. זוהי התנהגות לפיתוח בלבד ואינה משפיעה על הייצור. אם פונקציית העדכון שלך טהורה (כפי שהיא צריכה להיות), זה לא אמור להשפיע על ההתנהגות. התוצאה מאחת השיחות תתעלם.


שימוש

הוספת state לרכיב

התקשר ל-useState ברמה העליונה של הרכיב שלך כדי להכריז על אחד או יותר משתני state.

import { useState } from 'react';

function MyComponent() {
const [age, setAge] = useState(42);
const [name, setName] = useState('Taylor');
// ...

המוסכמה היא לתת שם למשתנים state כמו [something, setSomething] באמצעות הרס מערך.

useState מחזיר מערך עם שני פריטים בדיוק:

  1. הנוכחי state של משתנה state זה, מוגדר תחילה ל-state הראשוני שסיפקת.
  2. הפונקציה set המאפשרת לך לשנות אותה לכל ערך אחר בתגובה לאינטראקציה.

כדי לעדכן את מה שמופיע על המסך, קרא לפונקציה set עם state הבא:

function handleClick() {
setName('Robin');
}

React יאחסן את ה-state הבא, יעבד את הרכיב שלך שוב עם הערכים החדשים ויעדכן את ממשק המשתמש.

Pitfall

קריאה לפונקציה set לא משנה את ה-state הנוכחי בקוד שכבר מבצע:

function handleClick() {
setName('Robin');
console.log(name); // Still "Taylor"!
}

זה משפיע רק על מה שuseState יחזיר החל מהעיבוד הבא.

Basic useState examples

Example 1 of 4:
מונה (מספר)

בדוגמה זו, המשתנה count state מכיל מספר. לחיצה על הכפתור מגדילה אותו.

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}


עדכון state בהתבסס על state הקודם

נניח שה-age הוא 42. המטפל הזה קורא ל-setAge(age + 1) שלוש פעמים:

function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}

עם זאת, לאחר לחיצה אחת, age יהיה רק ​​43 ולא 45! זה בגלל שuse קורא לפונקציה set לא מתעדכנת למשתנה age state בקוד שכבר פועל. אז כל קריאת setAge(age + 1) הופכת ל-setAge(43).

כדי לפתור בעיה זו, תוכל להעביר פונקציית עדכון ל-setAge במקום ל-state הבא:

function handleClick() {
setAge(a => a + 1); // setAge(42 => 43)
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}

כאן, a => a + 1 היא פונקציית העדכון שלך. זה לוקח את בהמתנה state ומחשב את הבא state ממנו.

React מכניס את פונקציות העדכון שלך ל-תור. ואז, במהלך העיבוד הבא, הוא יקרא להם באותו סדר:

  1. a => a + 1 יקבל 42 כ-state הממתין ויחזיר את 43 כ-state הבא.
  2. a => a + 1 יקבל 43 כ-state הממתין ויחזיר את 44 כ-state הבא.
  3. a => a + 1 יקבל 44 כ-state הממתין ויחזיר את 45 כ-state הבא.

אין עדכונים אחרים בתור, אז React יאחסן 45 כ-state הנוכחי בסופו של דבר.

לפי המוסכמה, מקובל לתת שם לארגומנט הממתין state עבור האות הראשונה של שם המשתנה state, כמו a עבור age. עם זאת, אתה יכול גם לקרוא לזה כמו prevAge או משהו אחר שנראה לך ברור יותר.

React עשויה להתקשר לעדכונים שלך פעמיים בפיתוח כדי לוודא שהם טהורים.

Deep Dive

האם השימוש במעדכן תמיד מועדף?

ייתכן שתשמע המלצה לכתוב תמיד קוד כמו setAge(a => a + 1) אם ה-state שאתה מגדיר מחושב מה-state הקודם. אין בזה שום נזק, אבל זה גם לא תמיד הכרחי.

ברוב המקרים, אין הבדל בין שתי הגישות הללו. React תמיד מוודא שעבור פעולות user מכוונות, כמו קליקים, המשתנה age state יתעדכן לפני הקליק הבא. משמעות הדבר היא שאין סיכון שמטפל בלחיצות יראה age “מיושן” בתחילת המטפל באירועים.

עם זאת, אם אתה מבצע עדכונים מרובים באותו אירוע, עדכונים יכולים להיות מועילים. הם גם מועילים אם הגישה למשתנה state עצמו אינה נוחה (אתה עלול להיתקל בזה בעת אופטימיזציה של עיבוד מחדש).

אם אתה מעדיף עקביות על פני תחביר מעט יותר מילולי, סביר לכתוב תמיד עדכון אם ה-state שאתה מגדיר מחושב מה-state הקודם. אם זה מחושב מה-state הקודם של משתנה אחר state כלשהו, ​​אולי כדאי לשלב אותם לאובייקט אחד ו-use למפחית.

The difference between passing an updater and passing the next state directly

Example 1 of 2:
העברת פונקציית העדכון

דוגמה זו מעבירה את פונקציית העדכון, כך שכפתור “+3” עובד.

import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);

  function increment() {
    setAge(a => a + 1);
  }

  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <button onClick={() => {
        increment();
      }}>+1</button>
    </>
  );
}


עדכון אובייקטים ומערכים ב-state

אתה יכול לשים אובייקטים ומערכים לתוך state. ב-React, state נחשב לקריאה בלבד, אז עליך להחליף אותו במקום לשנות את האובייקטים הקיימים שלך. לדוגמה, אם יש לך אובייקט form ב-state, אל תשנה אותו:

// 🚩 Don't mutate an object in state like this:
form.firstName = 'Taylor';

במקום זאת, החלף את כל האובייקט על ידי יצירת אחד חדש:

// ✅ Replace state with a new object
setForm({
...form,
firstName: 'Taylor'
});

קרא את עדכון אובייקטים ב-state ו-עדכון מערכים ב-state למידע נוסף.

Examples of objects and arrays in state

Example 1 of 4:
טופס (אובייקט)

בדוגמה זו, המשתנה form state מכיל אובייקט. לכל קלט יש מטפל בשינוי שקורא ל-setForm עם ה-state הבא של הטופס כולו. תחביר התפשטות { ...form } מבטיח שהאובייקט state מוחלף במקום מוטציה.

import { useState } from 'react';

export default function Form() {
  const [form, setForm] = useState({
    firstName: 'Barbara',
    lastName: 'Hepworth',
    email: 'bhepworth@sculpture.com',
  });

  return (
    <>
      <label>
        First name:
        <input
          value={form.firstName}
          onChange={e => {
            setForm({
              ...form,
              firstName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Last name:
        <input
          value={form.lastName}
          onChange={e => {
            setForm({
              ...form,
              lastName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Email:
        <input
          value={form.email}
          onChange={e => {
            setForm({
              ...form,
              email: e.target.value
            });
          }}
        />
      </label>
      <p>
        {form.firstName}{' '}
        {form.lastName}{' '}
        ({form.email})
      </p>
    </>
  );
}


הימנעות מיצירה מחדש של ה-state הראשוני

React שומר את ה-state הראשוני פעם אחת ומתעלם ממנו בעיבודים הבאים.

function TodoList() {
const [todos, setTodos] = useState(createInitialTodos());
// ...

למרות שהתוצאה של createInitialTodos() היא רק used עבור העיבוד הראשוני, אתה עדיין קורא לפונקציה הזו בכל עיבוד. זה יכול להיות בזבזני אם זה יוצר מערכים גדולים או ביצוע חישובים יקרים.

כדי לפתור זאת, תוכל להעביר אותה כפונקציית initializer ל-useState במקום זאת:

function TodoList() {
const [todos, setTodos] = useState(createInitialTodos);
// ...

שימו לב שאתם מעבירים את createInitialTodos, שהיא הפונקציה עצמה, ולא את createInitialTodos(), שהיא התוצאה של הקריאה לה. אם תעביר פונקציה ל-useState, React יקרא לה רק במהלך האתחול.

React עשויה להתקשר לאתחולים שלך פעמיים בפיתוח כדי לוודא שהם טהורים.

The difference between passing an initializer and passing the initial state directly

Example 1 of 2:
העברת פונקציית האתחול

דוגמה זו מעבירה את פונקציית האתחול, כך שהפונקציה createInitialTodos פועלת רק במהלך האתחול. זה לא פועל כאשר רכיב מעבד מחדש, כגון כאשר אתה מקליד בקלט.

import { useState } from 'react';

function createInitialTodos() {
  const initialTodos = [];
  for (let i = 0; i < 50; i++) {
    initialTodos.push({
      id: i,
      text: 'Item ' + (i + 1)
    });
  }
  return initialTodos;
}

export default function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos);
  const [text, setText] = useState('');

  return (
    <>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={() => {
        setText('');
        setTodos([{
          id: todos.length,
          text: text
        }, ...todos]);
      }}>Add</button>
      <ul>
        {todos.map(item => (
          <li key={item.id}>
            {item.text}
          </li>
        ))}
      </ul>
    </>
  );
}


איפוס state עם מפתח

לעתים קרובות אתה תיתקל בתכונה key כאשר עיבוד רשימות. עם זאת, זה משרת גם מטרה אחרת.

אתה יכול לאפס state של רכיב על ידי העברת key אחר לרכיב. בדוגמה זו, כפתור האיפוס משנה את המשתנה version state, אותו אנו מעבירים כkey לForm. כאשר ה-key משתנה, React יוצר מחדש את הרכיב Form (וכל הילדים שלו) מאפס, כך שה-state שלו מתאפס.

קרא את שמירה ואיפוס state למידע נוסף.

import { useState } from 'react';

export default function App() {
  const [version, setVersion] = useState(0);

  function handleReset() {
    setVersion(version + 1);
  }

  return (
    <>
      <button onClick={handleReset}>Reset</button>
      <Form key={version} />
    </>
  );
}

function Form() {
  const [name, setName] = useState('Taylor');

  return (
    <>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <p>Hello, {name}.</p>
    </>
  );
}


אחסון מידע מעיבודים קודמים

בדרך כלל, תעדכן את state במטפלי אירועים. עם זאת, במקרים נדירים ייתכן שתרצה להתאים את state בתגובה לעיבוד — לדוגמה, ייתכן שתרצה לשנות משתנה state כאשר אבזר משתנה.

ברוב המקרים, אתה לא צריך את זה:

  • **אם ניתן לחשב את הערך שאתה צריך כולו מה-props הנוכחי או אחר state אחר, [הסר את ה-state המיותר הזה לגמרי.](/learn/choosing-the-state-structure#avoid-redundant-stateTroued about the re__0 Hook](/reference/react/useMemo) יכול לעזור.
  • אם ברצונך לאפס את כל ה-state של עץ הרכיבים, העבירו key אחר לרכיב שלכם.
  • אם אתה יכול, עדכן את כל ה-state הרלוונטיים במטפלי האירועים.

במקרה הנדיר שאף אחד מאלה לא חל, יש דפוס שאתה יכול use לעדכן את state בהתבסס על הערכים שעובדו עד כה, על ידי קריאה לפונקציה set בזמן שהרכיב שלך מעבד.

הנה דוגמה. רכיב CountLabel זה מציג את משענת count שהועברה אליו:

export default function CountLabel({ count }) {
return <h1>{count}</h1>
}

נניח שאתה רוצה להראות אם המונה עלה או ירד מאז השינוי האחרון. הפריט count לא אומר לך את זה — אתה צריך לעקוב אחר הערך הקודם שלו. הוסף את המשתנה prevCount state כדי לעקוב אחריו. הוסף משתנה state נוסף בשם trend כדי להחזיק אם הספירה גדלה או ירדה. השווה את prevCount ל-count, ואם הם לא שווים, עדכן גם את prevCount וגם את trend. עכשיו אתה יכול להראות גם את אבזר הספירה הנוכחי וגם איך הוא השתנה מאז העיבוד האחרון.

import { useState } from 'react';

export default function CountLabel({ count }) {
  const [prevCount, setPrevCount] = useState(count);
  const [trend, setTrend] = useState(null);
  if (prevCount !== count) {
    setPrevCount(count);
    setTrend(count > prevCount ? 'increasing' : 'decreasing');
  }
  return (
    <>
      <h1>{count}</h1>
      {trend && <p>The count is {trend}</p>}
    </>
  );
}

שים לב שאם אתה קורא לפונקציה set תוך כדי רינדור, היא חייבת להיות בתוך תנאי כמו prevCount !== count, וחייבת להיות קריאה כמו setPrevCount(count) בתוך התנאי. אחרת, הרכיב שלך יעבד מחדש בלולאה עד שהוא יקרוס. כמו כן, אתה יכול לעדכן רק את ה-state של רכיב המעבד כעת בצורה זו. קריאה לפונקציה set של רכיב אחר במהלך העיבוד היא שגיאה. לבסוף, הקריאה set שלך עדיין צריכה לעדכן state ללא מוטציה — זה לא אומר שאתה יכול לשבור כללים אחרים של פונקציות טהורות.

דפוס זה יכול להיות קשה להבנה ובדרך כלל עדיף להימנע ממנו. עם זאת, זה עדיף מאשר לעדכן את state באפקט. כאשר אתה קורא לפונקציה set במהלך העיבוד, React יעבד מחדש את הרכיב הזה מיד לאחר יציאת הרכיב שלך עם return statement, ולפני רינדור הילדים. בדרך זו, ילדים לא צריכים לעבד פעמיים. שאר פונקציית הרכיב שלך עדיין תתבצע (והתוצאה תיזרק). אם המצב שלך נמוך מכל הקריאות Hook, תוכל להוסיף return; מוקדם כדי להתחיל מחדש את העיבוד מוקדם יותר.


פתרון בעיות

עדכנתי את ה-state, אבל רישום נותן לי את הערך הישן

קריאה לפונקציה set לא משנה את state בקוד הפועל:

function handleClick() {
console.log(count); // 0

setCount(count + 1); // Request a re-render with 1
console.log(count); // Still 0!

setTimeout(() => {
console.log(count); // Also 0!
}, 5000);
}

זה בגלל use states מתנהגים כמו תמונת מצב. עדכון state מבקש עיבוד נוסף עם הערך החדש state, אך אינו משפיע על המשתנה count JavaScript הרץ שלך במשתנה המטפל שלך.

אם אתה צריך use את state הבא, אתה יכול לשמור אותו במשתנה לפני שתעביר אותו לפונקציה set:

const nextCount = count + 1;
setCount(nextCount);

console.log(count); // 0
console.log(nextCount); // 1

עדכנתי את state, אבל המסך לא מתעדכן

React יתעלם מהעדכון שלך אם ה-state הבא שווה ל-state הקודם, כפי שנקבע על ידי השוואה Object.is. זה קורה בדרך כלל כאשר אתה משנה אובייקט או מערך ב-state ישירות:

obj.x = 10; // 🚩 Wrong: mutating existing object
setObj(obj); // 🚩 Doesn't do anything

שינית אובייקט obj קיים והעברת אותו בחזרה ל-setObj, אז React התעלם מהעדכון. כדי לתקן זאת, עליך לוודא שאתה תמיד מחליף אובייקטים ומערכים ב-state במקום משנה אותם:

// ✅ Correct: creating a new object
setObj({
...obj,
x: 10
});

אני מקבל שגיאה: “יותר מדי עיבודים חוזרים”

אתה עשוי לקבל שגיאה שאומרת: Too many re-renders. React limits the number of renders to prevent an infinite loop. בדרך כלל, זה אומר שאתה מגדיר ללא תנאי את state במהלך העיבוד, כך שהרכיב שלך נכנס ללולאה: render, set state (שמאפשר עיבוד use), render, set state (וכן state), וכן __T. לעתים קרובות מאוד, זהו caused בטעות בציון מטפל באירוע:

// 🚩 Wrong: calls the handler during render
return <button onClick={handleClick()}>Click me</button>

// ✅ Correct: passes down the event handler
return <button onClick={handleClick}>Click me</button>

// ✅ Correct: passes down an inline function
return <button onClick={(e) => handleClick(e)}>Click me</button>

אם אינך מוצא את ה-cause של שגיאה זו, לחץ על החץ שליד השגיאה במסוף ועיין בערימת JavaScript כדי למצוא את קריאת הפונקציה הספציפית set האחראית לשגיאה.


פונקציית האתחול או העדכון שלי פועלת פעמיים

במצב קפדני, React יקרא לחלק מהפונקציות שלך פעמיים במקום פעם אחת:

function TodoList() {
// This component function will run twice for every render.

const [todos, setTodos] = useState(() => {
// This initializer function will run twice during initialization.
return createTodos();
});

function handleClick() {
setTodos(prevTodos => {
// This updater function will run twice for every click.
return [...prevTodos, createTodo()];
});
}
// ...

זה צפוי ולא אמור לשבור את הקוד שלך.

התנהגות זו של פיתוח בלבד עוזרת לך לשמור על רכיבים טהורים. React uses התוצאה של אחת הקריאות, ומתעלמת מהתוצאה של השיחה השנייה. כל עוד פונקציות הרכיב, האתחול והעדכון שלך טהורות, זה לא אמור להשפיע על ההיגיון שלך. עם זאת, אם הם בטעות טמאים, זה עוזר לך לשים לב לטעויות.

לדוגמה, פונקציית העדכון הלא טהורה הזו משנה מערך ב-state:

setTodos(prevTodos => {
// 🚩 Mistake: mutating state
prevTodos.push(createTodo());
});

Because React קורא לפונקציית העדכון שלך פעמיים, אתה תראה שהמטלה נוספה פעמיים, כדי שתדע שיש טעות. בדוגמה זו, אתה יכול לתקן את הטעות על ידי החלפת המערך במקום לשנות אותו:

setTodos(prevTodos => {
// ✅ Correct: replacing with new state
return [...prevTodos, createTodo()];
});

כעת, כשפונקציית העדכון הזו טהורה, לקרוא לזה זמן נוסף לא משנה בהתנהגות. זו הסיבה שReact קורא לזה פעמיים עוזר לך למצוא טעויות. רק פונקציות הרכיבים, האתחול והעדכון צריכות להיות טהורות. מטפלי אירועים אינם צריכים להיות טהורים, לכן React לעולם לא יתקשר למטפלי האירועים שלך פעמיים.

קרא את שמירה על רכיבים טהורים למידע נוסף.


אני מנסה להגדיר את state לפונקציה, אבל היא נקראת במקום זאת

אתה לא יכול להכניס פונקציה לתוך state בצורה הבאה:

const [fn, setFn] = useState(someFunction);

function handleClick() {
setFn(someOtherFunction);
}

מכיוון שuse אתה מעביר פונקציה, React מניח שsomeFunction היא פונקציית initializer, ושsomeOtherFunction היא [פונקציית עדכון](#עדכון-state-המבוסס על זה קודם לכן), התקשר אליהם ואחסן את התוצאה. כדי באמת לאחסן פונקציה, אתה צריך לשים לפניהם () => בשני המקרים. לאחר מכן React יאחסן את הפונקציות שאתה מעביר.

const [fn, setFn] = useState(() => someFunction);

function handleClick() {
setFn(() => someOtherFunction);
}