В чем разница между useState и useEffect? - PullRequest
0 голосов
/ 09 ноября 2018

Я видел эти две новые концепции, представленные в реакции v16.

Согласно моему пониманию:

useState похоже на setState с крючками и useEffectработает аналогично методам жизненного цикла.

Правильно ли мое понимание?Если нет, то какая точная разница между useState и useEffect?

Ответы [ 3 ]

0 голосов
/ 11 ноября 2018

Проще говоря, и useState, и useEffect улучшают функциональные компоненты, заставляя их делать то, что классы могут, но функциональные компоненты (без хуков) не могут:

  • useState позволяет функциональным компонентам иметь состояние , как this.state в компонентах класса.
  • useEffect позволяет функциональным компонентам иметь методы жизненного цикла (такие как componentDidMount, componentDidUpdate и componentWillUnmount) в одном API.

См. Примеры ниже для дополнительной иллюстрации:

useState

class CounterClass extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 1 };
  }
  
  render() {
    return <div>
      <p>Count: {this.state.count}</p>
      <button onClick={() => this.setState({ 
        count: this.state.count + 1
      })}>Increase</button>
    </div>;
  }
}

function CounterFunction() {
  const [count, setCount] = React.useState(1);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => 
        setCount(count + 1)}
      >Increase</button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <CounterClass />
    <CounterFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

useEffect

class LifecycleClass extends React.Component {
  componentDidMount() {
    console.log('Mounted');
  }
  
  componentWillUnmount() {
    console.log('Will unmount');
  }
  
  render() {
    return <div>Lifecycle Class</div>;
  }
}

function LifecycleFunction() {
  React.useEffect(() => {
    console.log('Mounted');
    return () => {
      console.log('Will unmount');
    };
  }, []); // Empty array means to only run once on mount.
  return (
    <div>Lifecycle Function</div>
  );
}

ReactDOM.render(
  <div>
    <LifecycleClass />
    <LifecycleFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

Подробнее о useState и useEffect на официальных документах React.

0 голосов
/ 24 марта 2019

useState и useEffect являются частью экосистемы хуков React 16.8+, целью которой является предоставление функциональным компонентам той же функциональности, которая ранее была доступна только для компонентов на основе классов (state / setState и методов жизненного цикла компонентов ( напр. componentDidMount, componentDidUpdate и componentWillUnmount)

useState() прост, он позволяет иметь доступ к состоянию внутри функционального компонента.

useEffect() может объединять componentDidMount, componentDidUpdate и componentWillUnmount, но это сложно.

Вы можете расшифровать большую часть того, что я должен обсудить здесь, из официальных документов для hooks . Легче увидеть хуки на работе, чем рассуждать по тексту.

Жизненный цикл предварительной визуализации

Предварительный рендеринг жизненного цикла события, эквивалентные componentWillReceiveProps или getDerivedStateFromProps и componentWillMount, могут быть просто вещами, которые мы делаем сначала в функциональном компоненте перед возвратом JSX (реагирующий узел) в качестве функции сам по себе эквивалентен render(…) методу компонента, основанного на классе.

Нам не нужны перехватчики для обработки событий жизненного цикла перед рендерингом.

Жизненный цикл после рендеринга

Жизненный цикл после рендеринга события, эквивалентные componentDidMount, componentDidUpdate и componentDidUnmount в компоненте на основе классов.

Нам нужно ****_useEffect(…)_** для обработки этих событий жизненного цикла пост-рендеринга **, поскольку мы не можем написать логику, связанную с этими событиями. События жизненного цикла внутри основной функции компонента, так как они должны запускаться после того, как функция компонента возвращает JSX (реагирующий узел) в react-dom средство визуализации.

Это означает, что у нас есть много, что мы можем сделать с крючками. Как?

Мы знаем useEffect(fn, […watchStates]), принимает 2 аргумента.

  1. fn: (обязательно) useEffect вызывает эту функцию для запуска в качестве побочного эффекта после каждого цикла рендеринга на основе отслеживаемых значений для изменений, заданных аргументом (2). Функция fn может возвращать другую функцию, которая должна быть запущена как очистка перед повторным запуском функции эффекта или отключением компонента
  2. […watchValues ]: (необязательно) useEffect значения треков в этом массиве изменились с последнего цикла рендеринга, после чего вызывается только эффект fn. Если этот аргумент не указан, эффект будет выполняться с каждым циклом рендеринга.

Если мы не передадим аргумент (2) все вместе, логика эффекта в fn будет вызываться после каждого цикла рендеринга.

Если мы передадим массив (2) со значениями, которые компонент должен отслеживать для изменений, и вызовем fn при изменении, довольно очевидно.

Самая сложная часть заключается в использовании пустого массива [] в качестве аргумента (2), мы можем ограничить логику побочных эффектов в fn, чтобы она выполнялась только во время фазы монтирования, так как нет изменений, за которыми следит ловушка эффекта. после последующих циклов рендеринга снова вызвать fn.

import React, { useState, useEffect } from "react";
export default props => {
  console.log("componentWillMount");
  console.log("componentWillReceiveProps", props);
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  const [moveCount, setMoveCount] = useState(0);
  const [cross, setCross] = useState(0);
  const mouseMoveHandler = event => {
    setX(event.clientX);
    setY(event.clientY);
  };
  useEffect(() => {
    console.log("componentDidMount");
    document.addEventListener("mousemove", mouseMoveHandler);
    return () => {
      console.log("componentDidUnmount");
      document.removeEventListener("mousemove", mouseMoveHandler);
    };
  }, []); // empty-array means don't watch for any updates
  useEffect(
    () => {
      // if (componentDidUpdate & (x or y changed))
      setMoveCount(moveCount + 1);
    },
    [x, y]
  );
  useEffect(() => {
    // if componentDidUpdate
    if (x === y) {
      setCross(x);
    }
  });
  return (
    <div>
      <p style={{ color: props.color }}>
        Your mouse is at {x}, {y} position.
      </p>
      <p>Your mouse has moved {moveCount} times</p>
      <p>
        X and Y positions were last equal at {cross}, {cross}
      </p>
    </div>
  );
};

Фрагмент кода прост и не требует пояснений. Вы можете попробовать это на CodePen .

Следует отметить одну важную вещь: если вы изменяете состояние внутри эффекта, убедитесь, что вы исключаете изменяющееся внутри него состояние из массива наблюдения.

Например, во втором эффекте (который подсчитывает движения мыши) мы запускаем его только при обновлении по x и y, передавая [x , y] в качестве второго аргумента, потому что

  1. Логически правильно наблюдать за изменениями x и y, чтобы зарегистрировать движение мыши
  2. Если мы не исключаем moveCount из отслеживаемого, этот useEffect войдет в бесконечный цикл, так как мы будем обновлять то же значение, которое мы также наблюдаем за изменениями

Эта статья также доступна в моей Средней публикации. Если вам нравится артиллерия, или у вас есть какие-либо комментарии и предложения, пожалуйста, хлоп или оставьте комментарии на Средний .

0 голосов
/ 09 ноября 2018

Для useState()

Во-первых, у нас есть функциональный компонент , который не поддерживается state, другими словами, функциональный компонент является компонент без состояния .

Теперь, с помощью хуков, у нас есть функциональный компонент , но с состоянием .Это достигается с помощью useState .


Для useEffect()

Во-первых, с функциональным компонентом без состояния , у нас нет крючки жизненного цикла компонента .Другими словами, всякий раз, когда вы хотите использовать ловушки жизненного цикла компонента , вы должны рассмотреть возможность использования компонента класса .

Теперь мы можем использовать жизненный цикл компонентаперехватывает без использования компонента класса .Это достигается с помощью useEffect .Другими словами, теперь, когда мы хотим использовать перехватчики жизненного цикла компонента , у нас уже есть две опции: использовать компонент класса или использовать перехватчики с useEffect.


ОБНОВЛЕНИЕ

Какова точная разница между useState и useEffect?

Проще говоря, useState позволяет нашему функциональных компонентов , которые раньше были без состояний становятся с состоянием useEffect позволяет нашим функциональным компонентам использовать ловушки жизненного цикла компонента , которые в прошлом поддерживались только для компонентов класса .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...