Repository: answerdev/answer
File: ui/src/pages/Tags/Edit/index.tsx (TypeScript)

Code before:
  const [focusType, setForceType] = useState('');

  const { data } = useTagInfo({ id: tagId });
  const { data: revisions = [] } = useQueryRevisions(data?.tag_id);
  const [formData, setFormData] = useState<FormDataItem>(initFormData);
  const [immData, setImmData] = useState(initFormData);
  const [contentChanged, setContentChanged] = useState(false);

  const editorRef = useRef<EditorRef>({
    getHtml: () => '',
  });

  usePromptWithUnload({
    when: contentChanged,
  });

  useEffect(() => {
    setFormData({
      ...formData,
      displayName: { ...formData.displayName, value: data?.display_name || '' },
      slugName: { ...formData.slugName, value: data?.slug_name || '' },
      description: {
        ...formData.description,
        value: data?.original_text || '',
      },
    });
  }, [data]);

  useEffect(() => {
    const { displayName, slugName, description, editSummary } = formData;
    const {
      displayName: display_name,
      slugName: slug_name,
      description: original_text,
    } = immData;
    if (!display_name || !slug_name || !original_text) {
      return;
    }

    if (
      display_name.value !== displayName.value ||
      slug_name.value !== slugName.value ||
      original_text.value !== description.value ||
      editSummary.value
    ) {
      setContentChanged(true);
    } else {
      setContentChanged(false);
    }
  }, [
    formData.displayName.value,

Review comment (suggestion):
You may have overlooked immData. immData is used to record the initial value. When the user changes the content and leaves the page, there will be a prompt; therefore, you need to add an assignment operation to immData here;


Code after:
  const [focusType, setForceType] = useState('');

  const { data } = useTagInfo({ id: tagId });
  const { data: revisions = [] } = useQueryRevisions(data?.tag_id);
  const [formData, setFormData] = useState<FormDataItem>(initFormData);
  const [immData, setImmData] = useState(initFormData);
  const [contentChanged, setContentChanged] = useState(false);

  const editorRef = useRef<EditorRef>({
    getHtml: () => '',
  });

  usePromptWithUnload({
    when: contentChanged,
  });

  useEffect(() => {
    initFormData.displayName.value = data?.display_name || '';
    initFormData.slugName.value = data?.slug_name || '';
    initFormData.description.value = data?.original_text || '';
    setFormData(initFormData);
    setImmData(initFormData);
  }, [data]);

  useEffect(() => {
    const { displayName, slugName, description, editSummary } = formData;
    const {
      displayName: display_name,
      slugName: slug_name,
      description: original_text,
    } = immData;

    if (
      display_name.value !== displayName.value ||
      slug_name.value !== slugName.value ||
      original_text.value !== description.value ||
      editSummary.value
    ) {
      setContentChanged(true);
    } else {
      setContentChanged(false);
    }
  }, [
    formData.displayName.value,
    formData.slugName.value,
    formData.description.value,
    formData.editSummary.value,
  ]);

  const handleDescriptionChange = (value: string) =>
    setFormData({