#reactjs #react-hooks #use-effect
Вопрос:
У меня проблема. просматривал здесь некоторые вопросы, но, похоже, это не работает для меня.
Я получаю эту ошибку на своих трех страницах, когда использую эффект использования.
Это код моего эффекта использования
const UserDetailsPage = () => {
const classes = useStyles()
const [userData, setUserData] = useState({
_id: "",
name: "",
phone: "",
address: "",
birthdate: "",
gender: "",
messenger: "",
photo: "",
email: "",
})
const [open, setOpen] = useState(false)
const [loaded, setLoaded] = useState(false)
const { height, width } = useWindowDimensions()
const {
_id,
name,
phone,
address,
photo,
gender,
messenger,
birthdate,
email,
} = userData
useEffect(() => {
const user = getUser()
getUserById("/user/" user.userId, user.token)
.then((data) => {
setUserData(data)
setLoaded(true)
})
.catch((error) => {
console.log(error)
})
}, [])
Ответ №1:
Если не getUserById
возвращать маркер отмены для отмены любых сетевых запросов на полеты или метод «отписки», вы можете использовать ссылку React для отслеживания того, все еще установлен компонент или нет, и не ставить в очередь обновление состояния, если компонент уже размонтирован.
const isMountedRef = React.useRef(false);
useEffect(() => {
isMountedRef.current = true;
return () => isMountedRef.current = false;
}, []);
useEffect(() => {
const user = getUser();
getUserById("/user/" user.userId, user.token)
.then((data) => {
if (isMountedRef.current) {
setUserData(data);
setLoaded(true);
}
})
.catch((error) => {
console.log(error);
});
}, []);
Комментарии:
1. Я предпочитаю это решение своему, так как
isMountedRef
его можно повторно использовать в компоненте, если внутри него несколько вызовов APIuseEffects
.2. @Moistbobo Это также не зависит от жизненного цикла «componentDidUpdate» других
useEffect
подключений с зависимостями.
Ответ №2:
Это связано с асинхронным вызовом в useEffect
завершении, а затем попыткой setState
сделать это после того, как страница больше не находится в фокусе.
Этого можно избежать путем рефакторинга useEffect
, например:
useEffect(() => {
// created a boolean to check if the component is mounted, name is arbitrary
let mounted = true;
const user = getUser();
getUserById("/user/" user.userId, user.token)
.then((data) => {
// only setState if mounted === true
if (mounted) {
setUserData(data);
setLoaded(true);
}
})
.catch((error) => {
console.log(error);
});
// set mounted to false on cleanup
return () => {
mounted = false;
};
}, []);
Отличие здесь в том, что я использую mounted
логическое значение для проверки того, смонтирована ли страница в данный момент. Заключив setState
вызов в состояние if, я могу проверить , безопасно ли это setState
, и таким образом избежать ошибки.
Ответ №3:
Это происходит, когда ваш компонент отключается перед настройкой состояния. Попробуйте выполнить этот код ниже, чтобы проверить, смонтирован компонент или нет.
useEffect(() => {
let isMounted = true; // add a flag to check component is mounted
getUserById("/user/" user.userId, user.token)
.then((data) => {
if(mounted) { // set state only when component is mounted
setUserData(data)
setLoaded(true)
}
})
.catch((error) => {
console.log(error)
})
return () => { isMounted = false }; // cleanup toggles value, if unmounted
}, []);
Ответ №4:
Не используйте асинхронные задачи в useEffect. Определите асинхронную функцию и вызовите свой эффект использования.
Пример:
const getSTH = async() =>{
getUserById("/user/" user.userId, user.token)
.then((data) => {
if(mounted) { // set state only when component is mounted
setUserData(data)
setLoaded(true)
}
})
.catch((error) => {
console.log(error)
})
}
useEffect (()=>{
getSTH();
},[])
Я думаю, что такой подход вам поможет.