如何在您的反应组件中使用效果钩
#javascript #react #typescript #hooks

React在版本16.8中引入钩子。钩子使我们能够创建具有状态和副作用的功能组件。

useEffect钩可帮助您在功能组件中创建副作用。

此钩将函数作为第一个参数和数组依赖性作为第二个参数。

效果必须在功能的正文中。如果您的效果需要清理,则可以返回函数执行它。

hook

function App() {
  const [count, setCount] = useState(0);
  const [timer, setTimer] = useState(false);

  const handleIncrease = () => setTimer((prevState) => !prevState);

  useEffect(() => {
    let timer1 = setTimeout(() => setCount((prevcount) => prevcount + 1), 2000);

    return () => {
      clearTimeout(timer1);
    };
  }, [timer]);

  return (
    <div>
      <p>count : {count}</p>
      <button onClick={handleIncrease} type="button">
        Launch Timer
      </button>
    </div>
  );
}

在这里,我们有一个钩子的示例。它执行一个计时器,该计时器将计数状态增加1。我们使用超时函数,这就是为什么我们需要清理功能来清除它。

数组依赖关系包含状态timer。我们使用它来触发useEffect

每次在我们的组件中更新状态时,它都会重新启动。如果timer已更新,则执行useEffect内部的功能。

当组件也卸下时,我们的清理功能将执行,以避免内存泄漏。

数组依赖性

使用数组依赖关系,我们可以选择钩中内部的函数执行何时。

在每个Rerender

要在安装座和每个rerender处执行它,请跳过数组依赖。

在山上

有一个空数组依赖性,只有在组件安装时才能执行您的效果。

在更新

每次更新数组依赖项中的值,在安装座时,挂钩将运行。

更多使用效果示例

现在,我们已经涵盖了useEffect钩的基础知识,让我们看一些如何使用它的示例。

从API获取数据

useEffect挂钩的一种常见用例是从API获取数据。

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
      setLoading(false);
    }

    fetchData();
  }, [userId]);

  if (loading) {
    return <Loading />;
  }

  return <Profile user={user} />;
}

我们使用useEffect挂钩在组件安装或userId prop更改时获取给定userId的用户数据。

我们在获取数据时将loading状态设置为true,然后在收到数据后将其更新为false

这使我们可以在获取数据时显示加载指示器,然后在数据可用后显示用户配置文件。

设置订阅

useEffect挂钩也可用于设置订阅,例如事件侦听器或Web套接字连接。

function Chat({ userId, onMessage }) {
  useEffect(() => {
    const socket = new WebSocket(`wss://chat.example.com/${userId}`);

    socket.addEventListener('message', onMessage);

    return () => {
      socket.removeEventListener('message', onMessage);
      socket.close();
    };
  }, [userId, onMessage]);

  // ...
}

在此示例中,我们使用useEffect挂钩来设置Web套接字连接和事件侦听器来传入消息。

useEffect钩子还包括一个清理功能,该功能可以删除事件侦听器并在组件卸下时关闭套接字连接。

添加事件听众

useEffect挂钩也可以用来将事件侦听器添加到DOM。

function WindowSize() {
  const [size, setSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    function handleResize() {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return (
    <div>
      Window size: {size.width} x {size.height}
    </div>
  );
}

在此示例中,我们使用useEffect钩将resize事件添加到页面上。在安装座时,可变大小的更新具有窗口的宽度和高度。当组件卸下时,清理功能会删除事件侦听器。

将使用效应与其他钩子相结合

useEffect挂钩可以与其他钩子(例如useStateuseContext)组合使用,以创建更复杂的逻辑。

例如,您可以使用useState钩管理用于触发效果的状态:

function Form() {
  const [submitting, setSubmitting] = useState(false);

  useEffect(() => {
    if (submitting) {
      // perform submission logic
    }
  }, [submitting]);

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
      <button type="submit" disabled={submitting}>
        Submit
      </button>
    </form>
  );
}

在此示例中,当submitting状态为true时,我们使用useEffect钩执行提交逻辑。这使我们可以在提交表单时禁用提交按钮并显示加载指示器。

您还可以使用useContext钩访问useEffect钩中的上下文值:

function UserList({ userId }) {
  const { users, dispatch } = useContext(UserContext);

  useEffect(() => {
    async function fetchUsers() {
      const response = await fetch(`/api/users?id=${userId}`);
      const data = await response.json();
      dispatch({ type: 'ADD_USERS', users: data });
    }

    fetchUsers();
  }, [userId, dispatch]);

  // ...
}

在此示例中,我们使用useEffect挂钩来获取基于userId prop的用户列表,并派遣操作将用户添加到上下文状态。

您可以使用useRef钩一次触发使用效果的内容。

function App() {
  const trigger = useRef(false);

  useEffect(() => {
    if (trigger.current) return;
    trigger.current = true;

    // your logic here...
  }, []);
  // ...
}

在此示例中,在MOUNT上,将执行useEffect的内容,并且trigger将更新为true。现在,useEffect的每个执行都将导致早期返回。

使用效果的最佳实践

使用useEffect挂钩时要记住一些最佳实践:

  • 注意效果的性能影响。避免使用过于频繁或计算昂贵的效果。
  • 使用数组依赖性来控制何时运行效果。这可以有助于避免不必要的重新租赁并提高性能。
  • 使用清理功能正确清理副作用,例如事件听众或网络请求。这可以帮助防止记忆泄漏。
  • 使用useCallback钩记录以依赖关系到useEffect钩的函数。这可以帮助避免不必要的重新租赁。
  • 更喜欢较小的useEffect。他们更容易理解和维护。

陷阱和要注意的东西

使用useEffect钩时有几件事要注意:

  • useEffect挂钩不同步,这意味着您不应依靠其副作用在下一个渲染之前完成。
  • 除非包含一个空数组依赖项,否则useEffect钩在初始渲染上不会运行。这意味着您不应使用useEffect钩子来设置初始渲染中使用的状态。
  • 请注意不要将值包括在数组依赖性中,以使变化过于频繁。这可能会导致useEffect挂钩运行太频繁,这可能会影响性能。

我希望这些信息有所帮助,并可以更好地了解React中的useEffect钩!

这篇文章是关于与TypeScript的React基础知识的系列。在Twitter上查看或follow me查找下一步。

稍后再见!