React Hooks - використовуючи useState vs просто змінні


12

Реактивні гачки дають нам параметр useState, і я завжди бачу порівняння Hooks та Class-State. А як же гачки та деякі регулярні змінні?

Наприклад,

function Foo() {
    let a = 0;
    a = 1;
    return <div>{a}</div>;
}

Я не використовував Гачки, і це дасть мені ті ж результати, що і:

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

То яка різниця? Використання гачків ще складніше для цього випадку ... То чому б почати його використовувати?


Ви порівнюєте 2 різні речі. Друга функція з гачками має можливість оновлювати дані. Перший насправді нічого не робить. Ви могли б просто ініціалізувати його, let a = 1; return <div>{a}</div>і ви отримаєте той самий результат.
Яті

Відповіді:


13

Причина полягає в тому, якщо ви useStateвідтворюєте думку. Змінні самі по собі змінюють лише біти пам'яті, і стан вашої програми може не синхронізуватися з поданням.

Порівняйте ці приклади:

function Foo() {
    const [a, setA] = useState(0);
    return <div onClick={() => setA(a + 1)}>{a}</div>;
}

function Foo() {
    let a = 0;
    return <div onClick={() => a + 1}>{a}</div>;
}

В обох випадках aзміни при натисканні, але лише при useStateправильному використанні представлення показує aпоточне значення.


Дякую! Тож якщо мені не потрібно відображати подання - лише спосіб впорядкувати мої дані (реквізити) в якийсь масив - я можу використовувати "нехай"? Це працює для мене, я просто хочу знати, що це добре і прийнятно.
Моше Нагар

@MosheNagar, якщо ви отримуєте свої дані від реквізиту, рекомендується використовувати локальні змінні, а не зберігати дані у стані, оскільки компонент все одно буде відображатися при зміні опори, так що представлення буде синхронізовано з даними. Переведення їх у стан призведе до лише непотрібної рендерингу - спочатку на зміну опори, потім на зміну стану.
marzelin

Ще один спосіб дивитися на цю відповідь - це думати, що у другому випадку змінна aбуде сміттям, зібраним після того, як вона закінчить виконання, а в першому, оскільки вона використовує, useStateвона збереже цінністьa
Жоао Маркос Гріс

Він все ще може використовувати, useRefякщо він не захотів переглянути вікно. Залишається питання, чи слід використовувати локальні змінні чи посилання React. Наприклад, якщо у вас є час очікування, який потрібно очистити, або постійний запит http, використовуючи axios, чи зберігаєте ви таймаут або джерело аксіосів у змінній або в React ref?
Том

3
@Tom Загальне правило - використовувати локальні vars для похідного стану. Для будь-чого іншого використовуйте useRef(якщо ви не хочете переказувати) або useState(якщо ви хочете передати). Що стосується таймерів, оскільки вони є побічними ефектами, їх слід починати useEffectгаком. Якщо ви хочете timerIdлише для очищення, ви можете зберегти його в локальній змінній обробника . Якщо ви хочете очистити таймер з іншого місця в компоненті, вам слід скористатися useRef. Збереження timerIdв локальній змінній компонента було б помилкою, оскільки локальні параметри "скидаються" на кожному візуалізації.
марзелін

1

Стан оновлення змусить компонент знову відтворити, але локальні значення - ні.

У вашому випадку ви вказали це значення у своєму компоненті. Це означає, що коли значення змінюється, компонент повинен бути повторно виведений для відображення оновленого значення.

Так що буде краще використовувати, useStateніж звичайне місцеве значення.

function Foo() {
    let a = 0;
    a = 1; // there will be no re-render.
    return <div>{a}</div>;
}

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // re-render required
    return <div>{a}</div>;
}

0

Ваш перший приклад працює лише тому, що дані по суті ніколи не змінюються. Точкою введення для використання setStateє відтворення всього вашого компонента, коли стан повіситься. Отже, якщо ваш приклад вимагав якихось змін стану чи управління, ви швидко зрозумієте, що зміни змін знадобляться, і для оновлення подання зі змінною величиною вам знадобиться стан та повторна візуалізація.


0
function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

еквівалентно

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 0
        };
    }
    // ...
}

Що useStateповертає - це дві речі:

  1. нова змінна стан
  2. сеттер для цієї змінної

якщо ви зателефонуєте, setA(1)ви б зателефонували this.setState({ a: 1 })та викликали повторну візуалізацію.


0

Локальні змінні отримають скидання кожного рендеру при мутації, тоді як стан оновиться:

function App() {
  let a = 0; // reset to 0 on render/re-render
  const [b, setB] = useState(0);

  return (
    <div className="App">
      <div>
        {a}
        <button onClick={() => a++}>local variable a++</button>
      </div>
      <div>
        {b}
        <button onClick={() => setB(prevB => prevB + 1)}>
          state variable b++
        </button>
      </div>
    </div>
  );
}

Редагуйте serene-galileo-ml3f0

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.