切换到另一页后,componentWillUnmount起作用

问题描述

我有两个页面和两个组件LibraryPageFilters.tsx(网址:/ courses)和UserVideoCreatePage.tsx(网址:/ ugc / courses / $ {course.id})。 在组件LibraryPageFilters.tsx

useEffect(() => {
    console.log(course.id)
    if (course.id) {
      console.log(544)
      dispatch(push(`/ugc/courses/${course.id}`));
    }
  },[course]);

我检查了存储中是否存在course.id,然后进行了重定向。 在组件UserVideoCreatePage.tsx

  useEffect(() => {
    return () => {
      console.log(333344444)
      dispatch(courseDelete());
    };
  },[]);

我在componentUnmount时正在从商店中删除课程。

enter image description here

为什么重定向后会发生卸载?结果,我被重定向回去。因为该课程在卸载时并未从存储中删除,并且检查(如果(course.id))表明该课程在存储中,并且发生了重定向dispatch(push(/ugc/courses/${course.id}) ))

UserVideoCreatePage.tsx

import React,{ useEffect,useRef,useState } from 'react';
import { shallowEqual,usedispatch,useSelector } from 'react-redux';
import { useParams } from 'react-router';
import { Link } from 'react-router-dom';

import { Container } from 'Core/components/Container/Container';
import { Svg } from 'Core/components/Svg';
import { Button } from 'Core/Molecules/Button';
import { Select } from 'Core/Molecules/Select';

import {
  agreementCourse,categoriesSelector,courseDelete,courseEditorCourseSelector,courseUpdateApi,getCategories,getCourse,updateCourseApi,} from 'Learnings/store/courseEdit';
import { CourseComments } from 'Learnings/screens/CoursePlayPage/CourseBottom/CourseComments/CourseComments';

import { AddItem } from './AddItem';
import s from 'Admin/Pages/Course/Description/index.scss';
import './UserVideoCreatePage.scss';

export const UserVideoCreatePage: React.FC = () => {
  const dispatch = usedispatch();
  const { id: idCourse } = useParams();
  const course = useSelector(courseEditorCourseSelector,shallowEqual);
  const categories = useSelector(categoriesSelector,shallowEqual);
  const [value,valueSet] = useState({ name: '',description: '',categories: [],lectures: [],materials: [] });
  const [tab,tabSet] = useState('program');
  const inputFileRef = useRef<HTMLInputElement>(null);
  const img = course.gallery_items && course.gallery_items[0];
  console.log(categories);
  const handleBtnClick = () => {
    if (inputFileRef && inputFileRef.current) {
      inputFileRef.current.click();
    }
  };

  useEffect(() => {
    dispatch(getCourse(idCourse));
    dispatch(getCategories());
  },[idCourse]);

  useEffect(() => {
    valueSet({
      name: course.name,description: course.description,categories: course.categories && course.categories[0] && course.categories[0].id,lectures: course.lectures,materials: course.materials,});
  },[course]);

  useEffect(() => {
    return () => {
      console.log(333344444)
      dispatch(courseDelete());
    };
  },[]);

  return (
    <Container className="createCourse">
      <Link to="/" className="gallery__back">
        <Svg name="arrow_back" width={26} height={20} className="gallery__svg"/>
        <span>Назад</span>
      </Link>

      <div className="createCourse__twoColumn">
        <div className="createCourse__twoColumn-left">
          <div className="inputBlock">
            <label className="inputBlock__label" htmlFor="video">
              Название видео-курса
            </label>
            <input
              id="video"
              type="text"
              placeholder="Введите название вашего видео"
              className="inputBlock__input"
              value={value.name || ''}
              onChange={e =>
                valueSet({
                  ...value,name: e.target.value,})
              }
              onBlur={e => {
                if (e.target.value && course.name !== e.target.value) {
                  dispatch(updateCourseApi(idCourse,{ name: e.target.value }));
                }
              }}
            />
          </div>
          <div className="inputBlock">
            <label className="inputBlock__label" htmlFor="opisanie">
              Описание видео-курса
            </label>
            <textarea
              id="opisanie"
              placeholder="Введите краткое описание вашего видео"
              className="inputBlock__input"
              value={value.description || ''}
              onChange={e =>
                valueSet({
                  ...value,description: e.target.value,})
              }
              onBlur={e => {
                if (e.target.value && course.description !== e.target.value) {
                  dispatch(updateCourseApi(idCourse,{ description: e.target.value }));
                }
              }}
            />
          </div>

          <Select
            title="Категории видео-курса"
            placeholder="Категории видео-курса"
            value={value.categories}
            options={categories.map(category => ({ value: category.id,label: category.name }))}
            onChange={val => {
              valueSet({
                ...value,categories: val,});

              dispatch(
                updateCourseApi(idCourse,{
                  category_ids: val,courses_curators: {
                    '': {
                      user_id: val,},}),);
            }}
            search
          />
        </div>

        <div className="createCourse__twoColumn-right">
          <div className="loadVideo">
            <div className="loadVideo__field">
              <div className="loadVideo__field--block">
                {!img && (
                  <>
                    <Svg className="loadVideo__field--block-icon" name="icn-load" width={104} height={69}/>
                    <p className="loadVideo__field--block-text">Загрузите обложку к видео</p>
                  </>
                )}
                {img && <img src={img && img.image_url} alt=""/>}
              </div>
            </div>
            <div className="loadVideo__under">
              <div className="loadVideo__under--left">
                <div className="loadVideo__under--text">
                  <span className="loadVideo__under--text-grey">*Рекомендуемый формат</span>
                  <span className="loadVideo__under--text-bold"> 356х100</span>
                </div>
                <div className="loadVideo__under--text">
                  <span className="loadVideo__under--text-grey">*Вес не должен превышать</span>
                  <span className="loadVideo__under--text-bold"> 10 Мб</span>
                </div>
              </div>
              <div className="loadVideo__under--right">
                <input
                  onChange={val => {
                    if (val.target.files[0]) {
                      if (img) {
                        dispatch(
                          updateCourseApi(idCourse,{
                            gallery_items: {
                              '': {
                                image: val.target.files[0],id: img.id,);
                      } else {
                        dispatch(
                          updateCourseApi(idCourse,);
                      }
                    }
                  }}
                  type="file"
                  ref={inputFileRef}
                  className="Library__btn"
                />
                <Button
                  onClick={() => {
                    handleBtnClick();
                  }}
                >
                  Библиотека обложек
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div className={`block-switcher block-switcher--courseCreate`}>
        <div
          className={`block-switcher__item ${tab === 'program' && 'block-switcher__item_active'}`}
          onClick={() => tabSet('program')}
        >
          Программы
        </div>
        <div
          className={`block-switcher__item ${tab === 'comments' && 'block-switcher__item_active'}`}
          onClick={() => tabSet('comments')}
        >
          Комментарии эксперта
        </div>
      </div>

      {tab === 'program' && (
        <>
          <AddItem
            accept="video/mp4,video/x-m4v,video/*"
            fieldName="name"
            addType="lecture_type"
            title="Видео-курсы"
            addBtn="Добавить видео"
            type="lectures"
            file="video"
            lecturesArg={course.lectures}
            value={value}
            onChangeInput={lecturesNew => {
              valueSet({
                ...value,lectures: lecturesNew,});
            }}
            onVideoUpdate={(params: any) => {
              dispatch(updateCourseApi(idCourse,params));
            }}
            posMove={(lectures: any) => {
              dispatch(courseUpdateApi({ id: idCourse,lectures: lectures },true));
            }}
          />
          <AddItem
            accept=""
            fieldName="title"
            addType="material_type"
            title="Материалы к видео-курсам"
            addBtn="Добавить файл"
            type="materials"
            file="document"
            lecturesArg={course.materials}
            value={value}
            onChangeInput={lecturesNew => {
              valueSet({
                ...value,materials: lecturesNew,materials: lectures },true));
            }}
          />
        </>
      )}

      {tab === 'comments' && <CourseComments title="Обсуждение"/>}

      <Button
        className={`${s.button} agreement__btn`}
        size="big"
        onClick={() =>
          dispatch(
            agreementCourse(idCourse,{
              visibility_all_users: true,)
        }
      >
        Отправить на согласование
      </Button>
    </Container>
  );
};

LibraryPageFilters.tsx

import React,useState } from 'react';
import { usedispatch,useSelector,shallowEqual } from 'react-redux';
import { push } from 'connected-react-router';

import { getSettingsGlobalSelector } from 'Core/store/settings';
import { Svg } from 'Core/components/Svg';
import { NavBar } from 'Core/Organisms/NavBar';
import { Button } from 'Core/Molecules/Button';
import { CategoriesFilter } from 'Core/Organisms/Filters/components/CategoriesFilter';

import { courseDelete,createNewCourse } from 'Learnings/store/courseEdit';

import { FILTERS,LINKS } from '../../libraryPageConstants';
import { setLibraryPageQuery } from '../../actions/libraryPageActions';
import { getLibraryPageQuerySelector } from '../../libraryPageSelectors';

import s from './index.scss';
import { languageTranslateSelector } from 'Core/store/language';
import { LanguageType } from 'Core/models/LanguageSchema';
import { Status,Tabs } from 'Core/components/Tabs/Tabs';

const statuses: Array<Status> = [
  {
    key: 'Filter/all',link: '/courses' || '/courses',type: 'all' || '',{
    key: 'Filter/online',link: '/courses/online',type: 'online',{
    key: 'Filter/offline',link: '/courses/offline',type: 'offline',{
    key: 'Filter/complete',link: '/courses/complete',type: 'complete',];

export const LibraryPageFilters = () => {
  const dispatch = usedispatch();
  const [searchTerm,setSearchTerm] = useState('');
  const [isBtndisabled,setIsBtndisabled] = useState(false);
  const course = useSelector(courseEditorCourseSelector,shallowEqual);

  const global = useSelector(getSettingsGlobalSelector);
  const query = useSelector(getLibraryPageQuerySelector,shallowEqual);
  const courseCreateButtonText = useSelector(
    languageTranslateSelector('CoursePage/courseCreateButton'),) as LanguageType;
  const { category_id: categoryID } = query;
console.log(course)
  useEffect(() => {
    console.log(course.id)
    if (course.id) {
      console.log(544)
      dispatch(push(`/ugc/courses/${course.id}`));
    }
  },[course]);

  useEffect(() => {
    return () => {
      setIsBtndisabled(false);
      dispatch(courseDelete());
    };
  },[]);

  const onFilter = (values: any) => {
    return false;
  };

  const handleActiveCategory = (id: number) => {
    const categoryParam = {
      ...query,offset: 0,category_id: id,};

    if (id === categoryID) {
      delete categoryParam.category_id;
    }

    dispatch(setLibraryPageQuery(categoryParam));
  };

  const handleSearch = () => {
    dispatch(setLibraryPageQuery({ query: searchTerm }));
  };

  return (
    <React.Fragment>
      <div className={s.filters}>
        {global.coursesPage?.filters.length ? (
          <NavBar
            className={s.navBar}
            links={global.coursesPage.filtersLinks.map(linkType => LINKS[linkType])}
            filters={global.coursesPage.filters.map(filterType => FILTERS[filterType])}
            onFilter={onFilter}
            postfix={
              global.coursesPage.courseCreateButton && global.coursesPage.courseCreateButton.enable ? (
                <Button
                  className="coursePageCreateButton"
                  onClick={() => {
                    dispatch(createNewCourse());
                    setIsBtndisabled(true);
                  }}
                  disabled={isBtndisabled}
                >
                  {courseCreateButtonText['CoursePage/courseCreateButton']}
                </Button>
              ) : null
            }
          />
        ) : (
          <div className="track-page__header" data-tut="track-header">
            <Tabs statuses={statuses} />
            <div className={s.filteRSSearch}>
              <Svg className={s.filteRSSearchIcon} name="search_alternative" width={18} height={18} />
              <input
                type="text"
                placeholder="Поиск"
                className={s.filteRSSearchInput}
                value={searchTerm}
                onChange={event => setSearchTerm(event.target.value)}
              />
              <button type="button" className={s.filtersButton} onClick={handleSearch}>
                Найти
              </button>
            </div>
          </div>
        )}
      </div>

      <CategoriesFilter onChange={handleActiveCategory} selectedID={categoryID} />
    </React.Fragment>
  );
};

解决方法

尽管 react 建议使用功能组件,尝试使用类组件,但我遇到了类似的问题,这在类组件中很容易解决:

componentDidMount();
componentDidUpdate(prevProps,prevState,snapshot);

这两个可以解决您的问题。问我您是否需要任何东西。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...