Reactjs 什么';处理未安装组件的错误的最佳方法是什么?正在尝试实现CKEditor,但出现此错误

Reactjs 什么';处理未安装组件的错误的最佳方法是什么?正在尝试实现CKEditor,但出现此错误,reactjs,react-redux,ckeditor,react-state,Reactjs,React Redux,Ckeditor,React State,将CKeditor实现为react模式后,我会出现以下错误: 警告:无法对已卸载的组件执行React状态更新。 这是一个no-op,但它表示应用程序中存在内存泄漏。 若要修复,请取消useEffect中的所有订阅和异步任务 清理功能 CKeditor出现在第132行,以下是实现代码: import { Avatar } from "@material-ui/core"; import { MoreHorizOutlined, ShareOutlined } from &quo

将CKeditor实现为react模式后,我会出现以下错误:

警告:无法对已卸载的组件执行React状态更新。 这是一个no-op,但它表示应用程序中存在内存泄漏。 若要修复,请取消useEffect中的所有订阅和异步任务 清理功能

CKeditor出现在第132行,以下是实现代码:

import { Avatar } from "@material-ui/core";
import { MoreHorizOutlined, ShareOutlined } from "@material-ui/icons";
import ArrowUpwardOutlinedIcon from "@material-ui/icons/ArrowUpwardOutlined";
import ArrowDownwardOutlinedIcon from "@material-ui/icons/ArrowDownwardOutlined";
import RepeatOutlinedIcon from "@material-ui/icons/RepeatOutlined";
import ChatBubbleOutlineOutlinedIcon from "@material-ui/icons/ChatBubbleOutlineOutlined";
import React, { useEffect, useState } from "react";
import "../style/Post.css";
import Modal from "react-modal";
import { useDispatch, useSelector } from "react-redux";
import {
  selectQuestionId,
  selectQuestionName,
  setQuestionInfo,
} from "../features/questionSlice";
import db from "../firebase";
import { selectUser } from "../features/userSlice";
import firebase from "firebase";
import ClassicEditor from "@ckeditor/ckeditor5-react";
import { CKEditor } from "@ckeditor/ckeditor5-build-classic";

Modal.setAppElement("#root");

function Post({ Id, question, imageUrl, timestamp, buildFaastUser }) {
  const user = useSelector(selectUser);
  const [openModal, setOpenModal] = useState(false);
  const dispatch = useDispatch();

  const questionId = useSelector(selectQuestionId);
  const questionName = useSelector(selectQuestionName);
  const [answer, setAnswer] = useState("");
  const [getAnswer, setGetAnswer] = useState([]);

  useEffect(() => {
    if (questionId) {
      db.collection("questions")
        .doc(questionId)
        .collection("answer")
        .orderBy("timestamp", "desc")
        .onSnapshot((snapshot) =>
          setGetAnswer(
            snapshot.docs.map((doc) => ({ id: doc.id, answers: doc.data() }))
          )
        );
    }
  }, [questionId]);

  const handleAnswer = (e) => {
    e.preventDefault();

    if (questionId) {
      db.collection("questions").doc(questionId).collection("answer").add({
        questionId: questionId,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
        answer: answer,
        user: user,
      });

      console.log(questionId, questionName);
      setAnswer("");
      setOpenModal(false);
    }
  };

  return (
    <div
      className="post"
      onClick={() =>
        dispatch(
          setQuestionInfo({
            questionId: Id,
            questionName: question,
          })
        )
      }
    >
      <div className="post__info">
        <Avatar src={buildFaastUser.photo} />
        <h5>
          {buildFaastUser.displayName
            ? buildFaastUser.displayName
            : buildFaastUser.email}
        </h5>
        <small>{new Date(timestamp?.toDate()).toLocaleString()}</small>
      </div>
      <div className="post__body">
        <div className="post__question">
          <p>{question}</p>
          <button
            onClick={() => setOpenModal(true)}
            className="post__btnAnswer"
          >
            Answer
          </button>

          <Modal
            isOpen={openModal}
            onRequestClose={() => setOpenModal(false)}
            shouldCloseOnOverlayClick={false}
            style={{
              overlay: {
                width: 680,
                height: 550,
                backgroundColor: "transparent",
                boxShadow:
                  "box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);",
                zIndex: "1000",
                top: "50%",
                left: "50%",
                marginTop: "-250px",
                marginLeft: "-350px",
              },
            }}
          >
            <div className="modal__question">
              <h1>{question}</h1>
              <p>
                asked by{" "}
                <span className="name">
                  {buildFaastUser.displayName
                    ? buildFaastUser.displayName
                    : buildFaastUser.email}
                </span>{" "}
                {""}
                on{" "}
                <span className="name">
                  {new Date(timestamp?.toDate()).toLocaleString()}
                </span>
              </p>
            </div>
            <div className="modal__answer">
              <CKEditor
                required
                editor={ClassicEditor}
                data={answer}
                onChange={(e, editor) => {
                  const data = editor.getData();
                  setAnswer(e.target.data);
                }}
                placeholder="Enter your answer"
                type="text"
              />
            </div>
            <div className="modal__button">
              <button className="cancel" onClick={() => setOpenModal(false)}>
                Cancel
              </button>
              <button onClick={handleAnswer} type="submit" className="add">
                Add Answer
              </button>
            </div>
          </Modal>
        </div>
        <div className="post__answer">
          {getAnswer.map(({ id, answers }) => (
            <p key={id} style={{ position: "relative", paddingBottom: "5px" }}>
              {Id === answers.questionId ? (
                <span>
                  {answers.answer}
                  <br />
                  <span
                    style={{
                      position: "absolute",
                      color: "gray",
                      fontSize: "small",
                      display: "flex",
                      right: "0px",
                    }}
                  >
                    <span style={{ color: "lightblue" }}>
                      {answers.user.displayName
                        ? answers.user.displayName
                        : answers.user.email}{" "}
                      on{" "}
                      {new Date(answers.timestamp?.toDate()).toLocaleString()}
                    </span>
                  </span>
                </span>
              ) : (
                ""
              )}
            </p>
          ))}
        </div>
        <img src={imageUrl} alt="" />
      </div>
      <div className="post__footer">
        <div className="post__footerAction">
          <ArrowUpwardOutlinedIcon />
          <ArrowDownwardOutlinedIcon />
        </div>

        <RepeatOutlinedIcon />
        <ChatBubbleOutlineOutlinedIcon />
        <div className="post__footerLeft">
          <ShareOutlined />
          <MoreHorizOutlined />
        </div>
      </div>
    </div>
  );
}

export default Post;
从“@material ui/core”导入{Avatar}”;
从“@material ui/icons”导入{MoreHorizOutlined,ShareOutlined}”;
从“@material ui/icons/ArrowUpwardOutlinedIcon”导入ArrowUpwardOutlinedIcon;
从“@material ui/icons/ArrowDownwardOutlinedIcon”导入ArrowDownwardOutlinedIcon;
从“@material ui/icons/RepeatOutlinedIcon”导入RepeatOutlinedIcon;
从“@material ui/icons/chatbugbleoutlined”导入chatbugbleoutlinedicon;
从“React”导入React,{useffect,useState};
导入“./style/Post.css”;
从“反应模态”导入模态;
从“react redux”导入{useDispatch,useSelector};
进口{
选择问题ID,
选择问题名称,
setQuestionInfo,
}来自“./features/questionSlice”;
从“./firebase”导入数据库;
从“./features/userSlice”导入{selectUser};
从“firebase”导入firebase;
从“@ckeditor/ckeditor5 react”导入ClassicEditor;
从“@CKEditor/ckeditor5 build classic”导入{CKEditor}”;
Modal.setAppElement(“#根”);
函数Post({Id,question,imageUrl,timestamp,buildFaastUser}){
const user=useSelector(selectUser);
const[openModal,setOpenModal]=useState(false);
const dispatch=usedpatch();
const questionId=useSelector(selectQuestionId);
const questionName=useSelector(selectQuestionName);
const[answer,setAnswer]=useState(“”);
常量[getAnswer,setGetAnswer]=useState([]);
useffect(()=>{
如果(问题ID){
db.收集(“问题”)
.doc(问题ID)
.收集(“答案”)
.orderBy(“时间戳”、“描述”)
.onSnapshot((快照)=>
设定答案(
snapshot.docs.map((doc)=>({id:doc.id,answers:doc.data()}))
)
);
}
},[questionId]);
常数handleAnswer=(e)=>{
e、 预防默认值();
如果(问题ID){
db.集合(“问题”).文档(问题ID).集合(“回答”).添加({
问号:问号,
时间戳:firebase.firestore.FieldValue.serverTimestamp(),
答:答,,
用户:用户,,
});
console.log(questionId、questionName);
设置应答(“”);
SetOpenModel(假);
}
};
返回(
派遣(
设置问题信息({
问题Id:Id,
问题名称:问题,
})
)
}
>
{buildFaastUser.displayName
?buildFaastUser.displayName
:buildFaastUser.email}
{新日期(时间戳?.toDate()).tolocalString()}
{问题}

SetOpenModel(真)} className=“post\uu btnAnswer” > 答复 setOpenModel(假)} shouldCloseOnOverlayClick={false} 风格={{ 覆盖:{ 宽度:680, 身高:550, 背景色:“透明”, boxShadow: “长方体阴影:0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);”, zIndex:“1000”, 顶部:“50%”, 左:“50%”, marginTop:“-250px”, marginLeft:“-350px”, }, }} > {问题} 由{“}提出 {buildFaastUser.displayName ?buildFaastUser.displayName :buildFaastUser.email} {" "} {""} 关于{“} {新日期(时间戳?.toDate()).tolocalString()}

{ const data=editor.getData(); 设置应答(如目标数据); }} 占位符=“输入您的答案” type=“text” /> setOpenModel(false)}> 取消 添加答案 {getAnswer.map({id,answers})=>(

{Id==answers.questionId( {答案。答案}
{answers.user.displayName ?answers.user.displayName :answers.user.email}{“} 关于{“} {新日期(answers.timestamp?.toDate()).tolocalString()} ) : ( "" )}

))} ); } 导出默认帖子;

我是一个新的反应,所以可能有一些基本的我错过了在执行方面。我肯定知道问题出在CKeditor实现上,但我不确定问题出在哪里,因为它是一个相当简单的组件。

我能够通过将装入的局部变量设置为true来消除未装入的错误,我在效果的清理函数中将其设置为false(如react所建议的)。然后我更新状态,当且仅当该值为真时,即如果
  useEffect(() => {
    let mounted = true;
    if (questionId) {
      db.collection("questions")
        .doc(questionId)
        .collection("answer")
        .orderBy("timestamp", "desc")
        .onSnapshot((snapshot) => {
          if (mounted) {
            setGetAnswer(
              snapshot.docs.map((doc) => ({ id: doc.id, answers: doc.data() }))
            );
          }
        });
    }

    return () => (mounted = false);
  }, [questionId]);