我在react-js中使用了多个标签,每个标签内容都是一个组件,比如下面的profile组件,它包含多个输入控件。我想在标签将被更改或组件将被销毁时调度一个updateUser动作。
我使用的是useEffect,所以通过向useEffect传递一个空的依赖数组([]),我可以确保在组件挂载时只运行一次效果,并且在组件卸载时运行清理函数但我想只在卸载组件时分派操作。
请大家帮我实现这个!
import React, { useEffect, useState } from 'react';
import '../User.scss';
import iconPhone from '../../../images/icon-phone.png';
import iconMail1 from '../../../images/icon-mail-01.png';
import iconMessageTextSquare1 from '../../../images/icon-message-text-square-01.png';
import { useAppDispatch, useAppSelector } from '../../../hooks/storeHooks';
import { UserDetails } from '../model/userDetails';
import { updateUser } from '../UserSlice';
import { isEqual } from 'lodash';
const Profile: React.FC = () => {
const [phoneExtension, setPhoneExtension] = useState('000');
const dispatch = useAppDispatch();
const currentUser = useAppSelector((state) => state.user.currentUser);
const initialUserState = currentUser || undefined;
const [user, setUser] = useState<UserDetails | undefined>(initialUserState);
const handleInputChange = (id: string, value: string) => {
setUser((prevUser) => ({
...(prevUser as UserDetails),
[id]: value,
}));
};
useEffect(() => {
let isMounted = true;
return () => {
isMounted = false;
if (currentUser && currentUser.id && user && isMounted) {
if (!isEqual(currentUser, user)) {
console.log('Changes detected. Dispatching update.');
dispatch(updateUser({ id: currentUser.id, user }));
} else {
console.log('No changes detected.');
}
}
};
}, []);
useEffect(() => {
return () => {
if (currentUser && currentUser.id && user) {
if (!isEqual(currentUser, user)) {
console.log('Changes detected. Dispatching update.');
dispatch(updateUser({ id: currentUser.id, user }));
} else {
console.log('No changes detected.');
}
}
};
}, []);
return (
<div className='flex flex-row flex-grow profile-block'>
<div className='card profile-card'>
<div className='header'>
<span className='title'>Profile</span>
<div>update your personal and company details here.</div>
</div>
<div className='body'>
<div className='profile-info'>
<div className='protext'>
<div className='text'>Personal info</div>
<p>Personal details and profile picture</p>
</div>
<div className='card'>
<form className='register-form'>
<div className='form-row'>
<div className='form-col'>
<label htmlFor='firstName'>First Name:</label>
<input
type='text'
id='firstName'
className='custom-input'
value={user?.firstName || ''}
onChange={(e) => {
handleInputChange('firstName', e.target.value);
}}
readOnly={false}
/>
</div>
<div className='form-col'>
<label htmlFor='lastName'>Last Name:</label>
<input
type='text'
id='lastName'
className='custom-input'
value={user?.lastName || ''}
onChange={(e) => {
handleInputChange('lastName', e.target.value);
}}
/>
</div>
</div>
<div className='form-row'>
<div className='form-col full-col'>
<label htmlFor='jobtitle'>Job Title:</label>
<input
type='text'
id='jobtitle'
className='custom-input'
value={user?.jobTitle || ''}
onChange={(e) => {
handleInputChange('jobTitle', e.target.value);
}}
/>
</div>
</div>
<div className='form-row'>
<div className='form-col col60'>
<label htmlFor='phoneNumber'>Office Number</label>
<div className='input-group'>
<div className='icon-block'>
<img src={iconPhone} alt='icon phone' />
</div>
<input
type='text'
id='phoneNumber'
className='custom-input'
value={user?.phoneNumber || ''}
onChange={(e) => {
handleInputChange('phoneNumber', e.target.value);
}}
/>
</div>
</div>
<div className='form-col col40'>
<label htmlFor='phoneExtension'>Phone Extension:</label>
<input
type='text'
id='phoneExtension'
className='custom-input'
value={phoneExtension}
onChange={(e) => {
setPhoneExtension(e.target.value);
}}
/>
</div>
</div>
</form>
</div>
</div>
<br />
<div className='divider'></div>
<br />
<br />
<div className='profile-info'>
<div className='protext'>
<div className='text'>Notification Contact Information</div>
<p>Details here will be blah blah blah for contact information for notifications. </p>
</div>
<div className='card'>
<form className='register-form'>
<div className='form-row'>
<div className='form-col full-col'>
<label htmlFor='notifyEmail'>Notify me by email</label>
<div className='input-group'>
<div className='icon-block'>
<img src={iconMail1} alt='icon email' />
</div>
<input
type='text'
id='notifyEmail'
className='custom-input'
value={user?.email || ''}
onChange={(e) => {
handleInputChange('email', e.target.value);
}}
/>
</div>
</div>
<div className='form-col full-col'>
<label htmlFor='notifySms'>Notify me by sms</label>
<div className='input-group'>
<div className='icon-block'>
<img src={iconMessageTextSquare1} alt='icon sms' />
</div>
<input
type='text'
id='notifySms'
className='custom-input'
value={user?.phoneNumber || ''}
onChange={(e) => {
handleInputChange('phoneNumber', e.target.value);
}}
/>
</div>
</div>
<div className='form-col full-col'>
<label htmlFor='notifySms'>Notify me by dialer</label>
<div className='input-group'>
<div className='icon-block'>
<img src={iconMessageTextSquare1} alt='icon sms' />
</div>
<input
type='text'
id='notifySms'
className='custom-input'
value={user?.dialer || ''}
onChange={(e) => {
handleInputChange('dialer', e.target.value);
}}
/>
</div>
</div>
<div className='form-col full-col'>
<label htmlFor='notifySms'>Notify me by pager</label>
<div className='input-group'>
<div className='icon-block'>
<img src={iconMessageTextSquare1} alt='icon sms' />
</div>
<input
type='text'
id='notifySms'
className='custom-input'
value={user?.pager || ''}
onChange={(e) => {
handleInputChange('pager', e.target.value);
}}
/>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
);
};
export default Profile;
字符串
1条答案
按热度按时间4xy9mtcn1#
这些情况的问题是,一方面,你希望清理只运行一次,但另一方面,你不能使用空的依赖数组,因为你需要更新的依赖。解决方案通常是使用ref。
选项1-将
currentUser
和user
保存在ref上:字符串
选项2:使用ref来保存卸载状态。这个ref应该由
useEffect
的cleanup函数更新,该函数在您的调度操作生效之前执行:型