如何修复无法在未安装的组件上执行React状态更新的问题?

我有一个简单的React组件,使用Axios从数据库中获取数据,它可以工作,但当我打开控制台时,我注意到以下错误。

index.js:1375 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

据我所知,为了解决这个问题,你需要使用 componentDidMount 和一个条件语句,但我不知道如何应用这个条件语句。useEffect 钩。如何解决这个错误?这是我的尝试。

import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import SecondColumn from '../SecondColumn/SecondColumn';
import Text from '../Text/Text';
import Pagination from "react-pagination-js";
import Spinner from '../Spinner/Spinner';

const Posts = () => {

  let [posts, setPosts] = useState([]);
  const [currentPage, setCurrentPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [postsPerPage] = useState(5);
  const isMounted = useRef(false)
  const GET_POSTS_API = process.env.REACT_APP_GET_POSTS_API;

  useEffect(() => {
    isMounted.current = true;
    const fetchPosts = async () => {
      setLoading(true);
      if (isMounted.current) {
        let res = await axios.get(GET_POSTS_API);
        setPosts(res.data);
        setLoading(false);
      }

    };

    fetchPosts();
    return () => { isMounted.current = false }
  }, []);

  // Get current posts
  const indexOfLastPost = currentPage * postsPerPage;
  const indexOfFirstPost = indexOfLastPost - postsPerPage;
  const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);

  if (loading) {
    return <Spinner />
  }

  // Change page
  const paginate = (pageNumber) => {
    if (pageNumber > 0) {
      setCurrentPage(pageNumber);
    }
  }

  return (
    <div className="row">
      <div className="column">
        {currentPosts.map(post => (
          <div key={post._id} className='post'>
            <img className="post-container__image" src={post.picture} alt="avatar" />
            <div className="post-container__post">
              <div className="post-container__text">
                <h2 className="post-container__title">{post.title}</h2>
                <p className="post-container__date">{post.date}</p>
                <p className="post-info-container__text">{post.postContent.substring(0, 310) + "..."}</p>
                <Link to={`/post/${post._id}`} className="read-more-btn">
                  <button className="read-more-btn">Read more</button>
                </Link>
              </div>
            </div>
          </div>
        ))}
        <Pagination
          currentPage={currentPage}
          currentPosts={currentPosts}
          showFirstLastPages={true}
          sizePerPage={postsPerPage}
          totalSize={posts.length}
          totalPages={posts.length}
          changeCurrentPage={paginate}
        />
        <Text />
      </div>
      <div className="column">
        <SecondColumn />
      </div>
    </div>
  )
};

export default Posts;

在应用了这里发布的所有解决方案后,没有一个能消除这个错误,我又调试了一下,发现在SecondColumn组件中,我有一个来自react-facebook包的组件FacebookProvider。当我删除这个组件的时候,我没有得到这个错误,但是我需要在页面上有这个组件,有什么想法吗,为什么这个包会导致这个错误,怎么解决呢,这里是SecondColumn的完整代码,FacebookProvider就在这里。

import React from 'react';
import titles from '../../enums.js'
import { FacebookProvider, Page } from 'react-facebook';
import CustomHeading from '../CustomHeading/CustomHeading.jsx'


class SecondColumn extends React.Component {

  render() {
    return <div className="second-column">

      <div className="second-column__about-me">
        <CustomHeading text={titles.ABOUT_ME} className="astro-heading-margin-left" />
        <img className="second-column__first_part__test-img-col" src={require("../../assets/images/fake-image.png")} alt="fake img for now" />
        <div className="second-column_first_part_text-parent">
          <p className="second-column_first_part_text-parent__text-body">Lorem ipsum dolor, sit amet consectetur adipisicing elit.
          Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id  Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id
          Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id  Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id
          Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id  Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id
           </p>
        </div>
      </div>

      <div className="second-column__first_part">
        <CustomHeading text={titles.MY_ASTROLOGICAL_READINGS} className="astro-heading-margin-left" />

        <img className="second-column__first_part__test-img-col" src={require("../../assets/images/fake-image.png")} alt="fake img for now" />
        <img className="second-column__first_part__test-img-col" src={require("../../assets/images/fake-image.png")} alt="fake img for now" />
        <img className="second-column__first_part__test-img-col" src={require("../../assets/images/fake-image.png")} alt="fake img for now" />
        <button className="btn">click here for all readings</button>
      </div>
      <div className="second-column__second_part">
        <h3 className="second-column__second_part__title"> Signs in a nutshell</h3>
        <div className="second-column__second_part__container">
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/002-aries.png")} alt="aries sign" />
            <p className="title">Aries</p>
          </div>

          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/022-taurus.png")} alt="taurus sign" />
            <p className="title">Taurus</p>
          </div>

          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/007-gemini.png")} alt="taurus sign" />
            <p className="title">Gemini</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/003-cancer.png")} alt="cancer sign" />
            <p className="title">Cancer</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/009-leo.png")} alt="leo sign" />
            <p className="title">Leo</p>
          </div>

          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/025-virgo.png")} alt="virgo sign" />
            <p className="title">Virgo</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/010-libra.png")} alt="libra sign" />
            <p className="title">Libra</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/020-scorpio.png")} alt="scorpio sign" />
            <p className="title">Scorpio</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/018-sagittarius.png")} alt="sagitarius sign" />
            <p className="title">Sagitarius</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/004-capricorn.png")} alt="capricorn sign" />
            <p className="title">Capricorn</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/001-aquarius.png")} alt="aquarius sign" />
            <p className="title">Aquarius</p>
          </div>
          <div className="item">
            <img className="item__astro-icon" src={require("../../assets/astro-signs/016-pisces.png")} alt="pisces sign" />
            <p className="title">Pisces</p>
          </div>
        </div>
      </div>
      <div className="second-column__third_part">
        <CustomHeading text={titles.DISCOVER_MORE_TOPICS} className="astro-heading-no-margin" />
        <div className="second-column__third_part-item">
          <div className="second-column__third-part-item__text">
            <p className="second-column__third-part-item__text_cont_title">Planets in astrology</p>
            <p className="second-column__third-part-item__text-cont">Lorem ipsum dolor, sit amet consectetur adipisicing elit.
            Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id

           </p>
          </div>
        </div>
        <div className="second-column__third_part-item">
          <div className="second-column__third-part-item__text">
            <p className="second-column__third-part-item__text_cont_title">Houses in Astrology</p>
            <p className="second-column__third-part-item__text-cont">Lorem ipsum dolor, sit amet consectetur adipisicing elit.
            Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id
          </p>
          </div>
        </div>
        <div className="second-column__third_part-item">
          <div className="second-column__third-part-item__text_cont">
            <p className="second-column__third-part-item__text_cont_title">Astrology Aspects</p>
            <p className="second-column__third-part-item__text-cont">Lorem ipsum dolor, sit amet consectetur adipisicing elit.
            Molestiae molestias tempora ratione dolorum, tenetur laborum blanditiis id
            </p>
          </div>
        </div>

      </div>
      <div className="second-column__fourth_part">
        <CustomHeading text={titles.CONNECT_WITH_ME_ON_FACEBOOK} className="astro-heading-no-margin" />
        <FacebookProvider appId="156975948863691">
          <Page href="https://www.facebook.com/UserName" tabs="timeline" />
        </FacebookProvider>
      </div>
    </div>
  }

};

export default SecondColumn;

解决方案:

isMounted 不需要是状态,它可以只是一个引用。

const isMounted = useRef(false);

然后在你的useEffect中,你可以把它设置为true。

useEffect(() => {
    isMounted.current = true;

你的useEffect函数也可以返回一个在卸载组件之前被调用的函数,这时你可以将isMounted设置为false:

useEffect(() => {
    isMounted.ref = true;
    ...
    return {() => { isMounted.current = false }
}, []);

测试你的组件是否被挂载了,你可以这样做。

if (isMounted.current) ...

给TA打赏
共{{data.count}}人
人已打赏
未分类

c中的变量隐藏和 "优先权"[重复]

2022-9-8 10:05:16

未分类

从SnifferModderHacker中隐藏Admob APP的ID。

2022-9-8 10:05:18

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索