React father::

effect

梗概

  • 在React中,effect是一个重要的概念,用于处理组件的副作用操作。副作用操作指的是对外部资源的访问,比如数据获取、订阅事件、手动修改DOM等。
  • 只能监听state
    • 因次想要触发effect, 就一定会导致组件重新渲染

实际应用

  • child::

    避免不必要的effect

    示例

    For example, you don’t need an Effect to adjust some state based on other state:

    function Form() {
      const [firstName, setFirstName] = useState('Taylor');
      const [lastName, setLastName] = useState('Swift');
     
      // 🔴 Avoid: redundant state and unnecessary Effect
      const [fullName, setFullName] = useState('');
      useEffect(() => {
        setFullName(firstName + ' ' + lastName);
      }, [firstName, lastName]);
      // ...
    }

    上面的写法是多余的,和下面代码的作用完全一致:

    function Form() {
      const [firstName, setFirstName] = useState('Taylor');
      const [lastName, setLastName] = useState('Swift');
      // ✅ Good: calculated during rendering
      const fullName = firstName + ' ' + lastName;
      // ...
    }
    指向原始笔记的链接
指向原始笔记的链接

使用effect

在函数式组件中使用effect时,可以通过useEffect来定义effect函数。该函数会在组件渲染完成后执行,并且可以返回一个清除函数用于清理effect。

useEffect(() => {
  // effect逻辑
  return () => {
    // 清理逻辑
  };
}, [dependencies]);

控制effect执行时机

  • base::effect执行时机
  • 可以通过第二个参数传入一个数组。effect会监听数组元素的变化
    • 在目标变化调用回调函数(其实还要先调用清理函数)
      • 所以直接访问state就是更新后的值
  • 如果不传入依赖项数组,它只会在组件挂载时运行一次(类似于 componentDidMount)。

监听props变化

  • 虽然props是常量,但useEffect可以监听props的变化
    • 每当父组件传入新的props值时,子组件会重新渲染
    • useEffect可以通过依赖数组监听到props的变化
  • 这对于需要响应props变化执行副作用操作很有用
    • 例如:基于props变化更新组件内部状态、触发API调用等
function ProfilePage({ userId }) {
  const [userData, setUserData] = useState(null);
  
  // 当userId props变化时,重新获取用户数据
  useEffect(() => {
    async function fetchUserData() {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUserData(data);
    }
    
    fetchUserData();
  }, [userId]); // 监听userId props变化
  
  if (!userData) return <div>Loading...</div>;
  return <div>{userData.name}'s Profile</div>;
}

代码示例

import React, { useEffect, useState } from 'react';
 
const MyComponent = () => {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    document.title = `You clicked ${count} times`;
    return () => {
      document.title = 'React App';
    };
  }, [count]);
 
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
};
 
export default MyComponent;

这个例子中,我们使用useEffect来监听count的变化。每次点击按钮增加计数时,页面的标题也会随之改变。同时,我们在返回的清理函数中将标题还原为默认值。

异步与清理