注释从这开始~

总览

为了解决"Warning: Can't perform a React state update on an unmounted component" ,能够在你的useEffect钩子中申明一个isMounted布尔值,用来跟踪组件是否被装置。一个组件的状态只有在该组件被挂载时才会被更新。

import {useState, useEffect} from 'react';const App = () => {  const [state, setState] = useState('');  useEffect(() => {    // ️ set isMounted to true    let isMounted = true;    async function fetchData() {      const result = await Promise.resolve(['hello', 'world']);      // ️ only update state if component is mounted      if (isMounted) {        setState(result);      }    }    fetchData();    return () => {      // ️ when component unmounts, set isMounted to false      isMounted = false;    };  }, []);  return (    <div>      <h2>State: {JSON.stringify(state)}</h2>    </div>  );};export default App;
当咱们试图更新一个未挂载的组件的状态时,会呈现"无奈在未挂载的组件上执行React状态更新"的正告。

isMounted

解脱该正告的含糊其辞的形式是,在useEffect钩子中应用isMounted布尔值来跟踪组件是否被挂载。

useEffect中,咱们初始化isMounted布尔值为true

咱们的fetchData 函数执行一些异步的工作,最常见的是一个API申请,并依据响应来更新状态。

然而,须要留神的是,咱们只有当isMounted变量被设置为true时,才会更新状态。

async function fetchData() {  const result = await Promise.resolve(['hello', 'world']);  // ️ only update state if component is mounted  if (isMounted) {    setState(result);  }}

这能够帮忙咱们防止正告,因为如果组件没有挂载,咱们就不会更新状态。

当组件卸载时,从useEffect钩子返回的函数会被调用。

return () => {  // ️ when component unmounts, set isMounted to false  isMounted = false;};

咱们设置isMounted变量为false,示意该组件不再挂载。如果fetchData函数在组件卸载时被调用,if代码块不会执行是因为isMounted设置为false

async function fetchData() {  const result = await Promise.resolve(['hello', 'world']);  // ️ only update state if component is mounted  if (isMounted) {    setState(result);  }}

提取

如果常常这样做,能够将逻辑提取到可重用的钩子中。

import {useState, useEffect, useRef} from 'react';// ️ extract logic into reusable hookfunction useIsMounted() {  const isMounted = useRef(false);  useEffect(() => {    isMounted.current = true;    return () => {      isMounted.current = false;    };  });  return isMounted;}const App = () => {  const [state, setState] = useState('');  // ️ use hook  const isMountedRef = useIsMounted();  useEffect(() => {    async function fetchData() {      const result = await Promise.resolve(['hello', 'world']);      // ️ only update state if component is mounted      if (isMountedRef.current) {        setState(result);      }    }    fetchData();  }, [isMountedRef]);  return (    <div>      <h2>State: {JSON.stringify(state)}</h2>    </div>  );};export default App;

useRef()钩子能够传递一个初始值作为参数。该钩子返回一个可变的ref对象,其.current属性被初始化为传递的参数。

咱们在useIsMounted钩子中跟踪组件是否被挂载,就像咱们间接在组件的useEffect钩子中做的那样。

须要留神的是,在fetchData函数中,咱们必须查看isMountedRef.current 的值,因为ref上的current属性是ref的理论值。