问题描述
我有两个页面和两个组件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时正在从商店中删除课程。
为什么重定向后会发生卸载?结果,我被重定向回去。因为该课程在卸载时并未从存储中删除,并且检查(如果(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);
这两个可以解决您的问题。问我您是否需要任何东西。