从带有回调的 this.setState 调用迁移到 useState 和 useEffect
Posted
技术标签:
【中文标题】从带有回调的 this.setState 调用迁移到 useState 和 useEffect【英文标题】:Migrate from this.setState calls with callback to useState and useEffect 【发布时间】:2020-06-23 11:45:15 【问题描述】:我已经使用新的 react 钩子将近 4 个月了,这是创建 react 组件的一个很好的调整。目前,我正在尝试从类组件迁移到功能组件并遇到一些问题。 例如,让我们讨论这个案例并比较函数和类组件以更好地理解问题。
class UserInformation extends React.Component
state =
isBusy: false,
;
updateImage = (uploadedImageData: IUploadImage): void =>
const imageData =
ImageData: base64ToArrayBuffer(uploadedImageData.ImageData.ImageData),
FileName: uploadedImageData.FileName,
;
this.setState( isBusy: true , () =>
this.props.updateSettingsUserImage(this.props.selectedUser, imageData)
.then(() => this.setState( isBusy: false ));
);
;
deleteImage = (): void =>
this.setState( isBusy: true , () =>
this.props.deleteSettingsUserImage(this.props.selectedUser)
.then(() => this.setState( isBusy: false ));
);
;
const selectedUser = this.props;
return (
<BaseInfoCardHeader
withUploadableAvatar
style= margin: '0 -12px'
name=selectedUser.FullName
deleteImage=this.deleteImage
updateImage=this.updateImage
photopath=selectedUser.Photopath
/>
);
export default UserInformation;
这里是UserInformation的功能组件版本
const UserInformation = (props) => const [isBusy, setIsBusy] = useState(false);
const updateImage = (uploadedImageData: IUploadImage): void =>
const imageData =
ImageData: base64ToArrayBuffer(uploadedImageData.ImageData.ImageData),
FileName: uploadedImageData.FileName,
;
setIsBusy(true);
;
const deleteImage = (): void => setIsBusy(true);
useEffect(() =>
if (isBusy)
updateSettingsUserImage(props.selectedUser, imageData)
.then(() => setIsBusy(false));
, [isBusy]);
useEffect(() =>
if (isBusy)
deleteSettingsUserImage(props.selectedUser)
.then(() => setIsBusy(false));
, [isBusy]);
const selectedUser = this.props;
return (
<BaseInfoCardHeader
withUploadableAvatar
style= margin: '0 -12px'
name=selectedUser.FullName
deleteImage=this.deleteImage
updateImage=this.updateImage
photopath=selectedUser.Photopath
/>
);
export default UserInformation;
我们可以看到,在功能组件内部,无论是触发 updateImage 还是 deleteImage,都将运行 2 个 useEffects 并进行 API 调用。但是在类组件中,API 调用将在 setState 回调中处理,并且只会请求一个 API 调用。 一种选择是为 imageData 添加另一个状态并在其 useEffect 依赖项列表中使用它。但是如果我们没有 imageData 并且一切都依赖于 isBusy 怎么办。处理这种情况的最佳方法是什么?
【问题讨论】:
【参考方案1】:为什么你甚至需要在这个组件中设置状态?还要注意不要仅仅将类组件转换为功能组件,因为它的新颖性,基于类的组件仍然有它们的位置。但你的例子实际上是一个很好的候选者。
const UserInformation = (props) =>
const [isBusy, setBusy] = useState(false)
const updateImage = async (uploadedImageData: IUploadImage): void =>
setBusy(true);
const imageData =
ImageData: base64ToArrayBuffer(uploadedImageData.ImageData.ImageData),
FileName: uploadedImageData.FileName,
;
await updateSettingsUserImage(props.selectedUser, imageData)
setBusy(false);
;
const deleteImage = async (): void =>
setBusy(true);
await deleteSettingsUserImage(props.selectedUser);
setBusy(false);
const selectedUser = props;
return (
<BaseInfoCardHeader
withUploadableAvatar
style= margin: '0 -12px'
name=selectedUser.FullName
deleteImage=this.deleteImage
updateImage=this.updateImage
photopath=selectedUser.Photopath
/>
);
export default UserInformation;
【讨论】:
那么如何使用 isBusy 呢?我需要它在获取时处理动画。 好的,如果您需要isBusy,请查看更新后的答案以上是关于从带有回调的 this.setState 调用迁移到 useState 和 useEffect的主要内容,如果未能解决你的问题,请参考以下文章