useState和useEffect有什么区别?

Hem*_*ari 4 javascript reactjs react-native react-hooks

我已经看到了反应v16中引入的这两个新概念.

据我了解:

useStatesetState与钩子类似,其useEffect工作方式与生命周期方法类似.

我的理解是否正确?如果没有,useState和之间的确切区别是useEffect什么?

Sim*_*ngh 7

useState并且useEffect是 React 16.8+ hooks 生态系统的一部分,该生态系统旨在为 Functional 组件提供与以前仅适用于基于类的组件(state/setState和组件生命周期方法(例如componentDidMountcomponentDidUpdate, 和componentWillUnmount))相同的功能

useState() 很简单,它允许您在功能组件中拥有状态访问器。

useEffect() 可以结合componentDidMount, componentDidUpdate, andcomponentWillUnmount但很棘手。

您可以从hooks 的官方文档中解读我在这里讨论的大部分内容。看到工作中的钩子比从文本中推理更容易。

预渲染生命周期

预渲染生命周期事件相当于componentWillReceivePropsorgetDerivedStateFromProps并且componentWillMount可以只是我们在返回 JSX(反应节点)之前首先在功能组件中做的事情,因为函数本身相当于render(…)基于类的组件的方法。

我们不需要钩子来处理预渲染生命周期事件。

渲染后生命周期

渲染后生命周期事件,相当于componentDidMount,componentDidUpdatecomponentDidUnmount基于类的组件中的事件。

我们需要****_useEffect(…)_** 来处理这些渲染后生命周期事件** 因为我们无法在主组件函数中编写与这些生命周期事件相关的逻辑,因为这些应该在组件函数将 JSX(react-node)返回给react-dom渲染器之后运行.

这意味着,我们可以用钩子做很多事情。如何?

我们知道useEffect(fn, […watchStates]),接受 2 个参数。

  1. fn:(必需)useEffect调用此函数以在每个渲染周期后根据正在跟踪的值以获取由 (2) 参数给出的更改作为副作用运行。该函数fn可以返回另一个应该在效果函数再次运行或组件卸载之前作为清理运行的函数
  2. […watchValues ]:(可选)useEffect跟踪此数组中的值已从上一个渲染周期更改,然后仅fn调用效果。如果未给出此参数,则效果将在每个渲染周期中运行。

如果我们不一起传递 (2) 参数,fn将在每个渲染周期后调用效果逻辑 in 。

如果我们传递带有值的 (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>
  );
};
Run Code Online (Sandbox Code Playgroud)

代码片段很简单,一目了然。您可以在CodePen试用

需要注意的一件重要事情是,如果您在效果内部进行状态更改,请确保从监视数组中排除内部正在更改的状态。

例如,在第二个效果(计算鼠标移动的效果)中,我们仅在 x 和 y 上的更新时触发它,[x , y]作为第二个参数传递,因为

  1. 观察 x 和 y 的变化以注册鼠标移动在逻辑上是正确的
  2. 如果我们不排除 moveCount 被观察,这个 useEffect 将进入一个无限循环,因为我们将更新我们也在观察变化的相同值

这篇文章也可以在我的Medium出版物上发表。如果您喜欢本文,或有任何意见和建议,请在Medium鼓掌发表评论


Yan*_*Tay 6

简单地说,无论是useStateuseEffect增强功能组件,使他们做的事情,类可以,但功能部件(无钩)不能:

  • useState允许功能组件具有state,就像this.state在类组件中一样。
  • useEffect允许功能部件有生命周期方法(如componentDidMountcomponentDidUpdatecomponentWillUnmount)在一个单一的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'));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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'));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

在官方的React文档上阅读有关useStateuseEffect的更多信息。


Ngu*_*You 5

对于 useState()

首先,我们有不支持的功能组件,state换句话说,功能组件无状态组件.

现在,有了Hooks,我们有功能组件有状态.它是通过使用useState实现的.


对于 useEffect()

首先,使用无状态功能组件,我们没有组件生命周期钩子.换句话说,只要您想使用组件生命周期钩子,就应该考虑使用类组件.

现在,我们可以在不使用类组件的情况下使用组件生命周期钩子.它是通过使用useEffect实现的.换句话说,现在每当我们想要使用组件生命周期钩子时,我们已经有两个选项使用类组件或使用Hooks .useEffect


UPDATE

什么是useState和之间的确切区别useEffect

简单来说,useState允许我们过去无国籍的功能组件变为有状态.并允许我们的功能组件利用组件生命周期钩子,这些钩子过去仅支持类组件.useEffect