![](/img/trans.png)
[英]React: SetInterval in ComponentDidMount causing error "Warning: Can't perform a React state update on an unmounted component."
[英]React Warning: Can't perform a React state update on an unmounted component. To fix, cancel all subscriptions
嘗試更改模態內的值時收到上述警告:
我有一個彈出窗口,當我更改模式中國家/地區代碼字段的值時,一切正常。 但是一旦我保存或關閉模態,狀態變量的值就變得未定義。
主模態文件:
const EditDetailsModal = props => {
const dispatch = useDispatch()
const intl = useIntl()
const shouldShowModal = useSelector(selectors.shouldShowEditDetailsModal)
const name = useSelector(selectors.getName)
const email = useSelector(selectors.getEmail)
const phoneNumber = useSelector(selectors.getPhone)
const country = useSelector(selectors.getCountry)
const phoneCode = useSelector(selectors.getPhoneCountryCode)
const [newName, setNewName] = React.useState(name)
const [newEmail, setNewEmail] = React.useState(email)
const [newPhone, setNewPhone] = React.useState(phoneNumber)
const [newPhoneCode, setNewPhoneCode] = React.useState(phoneCode)
const _handleOnModalHide = React.useCallback(() => {
setNewEmail(email)
setNewName(name)
setNewPhone(phoneNumber)
setNewCountry(country)
setRequestPhoneValue(phoneNumber)
dispatch(actions.hideEditDetailsModal())
}, [dispatch, name, setNewName, email, newEmail, setNewEmail, phoneNumber, setNewPhone, country, setNewCountry, setRequestPhoneValue ])
const _phoneCountryCodeChangeCallback = React.useCallback((code) => {
setNewPhoneCode(code)
},[setNewPhoneCode])
const _handleSaveBtnClick = React.useCallback(() => {
if (isSaveBtnActive) {
dispatch(actions.startRequestEditPersonalDetails())
setError('')
editPersonalDetails({
name: newName,
email: newEmail,
phone: requestPhoneValue,
country: requestCountryValue,
oldEmail: email,
phone_code: newPhoneCode,
}).then(response => {
if (response && response.data && response.data.data) {
dispatch(actions.successEditPersonalDetails())
dispatch(actions.savePersonalDetails(response.data.data))
_handleOnModalHide()
} else {
dispatch(actions.errorEditPersonalDetails())
if (response.data.errors[0] && response.data.http_message) {
setError(response.data.errors[0])
} else {
setError(intl.formatMessage({
id: "error.commonServerError"
}))
}
}
}).catch(error => {
dispatch(actions.errorEditPersonalDetails())
setError(intl.formatMessage({
id: "error.commonServerError"
}))
})
}
}, [newName, newEmail, requestPhoneValue, requestCountryValue, isSaveBtnActive])
// handle response change
React.useEffect(() => {
setNewName(name)
}, [name, setNewName, shouldShowModal])
React.useEffect(() => {
setNewEmail(email)
}, [email, setNewEmail, shouldShowModal])
React.useEffect(() => {
setNewPhone(phoneNumber)
setRequestPhoneValue(phoneNumber)
}, [phoneNumber, setNewPhone, setRequestPhoneValue, shouldShowModal])
React.useEffect(() => {
setNewCountry(getCountryFromCode(country))
setRequestCountryValue(country)
}, [country, setNewCountry, setRequestCountryValue, shouldShowModal])
React.useEffect(() => {
setNewPhoneCode(phoneCode)
}, [phoneCode, setNewPhoneCode, shouldShowModal])
return (
<div onClick={e => e.stopPropagation()}>
<Modal
show={shouldShowModal}
onHide={_handleOnModalHide}
className="editModal"
backdropClassName="edit-details-modal-backdrop-custom"
centered>
<FormContainer>
<BlockUi tag="div" blocking={isRequestLoading}>
<Modal.Header className="editModalHeader" closeButton>
<Modal.Title>
<FormattedMessage id="modal.editPersonalDetails.title"/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formBasicPhoneNumber">
<ModalPhoneInput
initialValue={newPhone}
changeCallback={_phoneChangeCallback}
countryChangeCallback={_phoneCountryCodeChangeCallback}
defaultCountryCode={newPhoneCode}/>
</Form.Group>
<SaveDetailsBtn
disabled={!isSaveBtnActive}
onClick={_handleSaveBtnClick}>
<FormattedMessage id="modal.editPersonalDetails.save"/>
</SaveDetailsBtn>
</Form>
</Modal.Body>
</BlockUi>
</FormContainer>
</Modal>
</div>
)
}
和 PhoneNumberInput 文件:
const PhoneNumberInput = ({ initialValue, customPlaceholder, changeCallback,countryChangeCallback, defaultCountryCode, ...props }) => {
const [countryCode, setCountryCode] = React.useState(defaultCountryCode.toUpperCase())
const _handleOnCountryCodeChange = React.useCallback((code) => {
countryChangeCallback(code)
},[countryChangeCallback])
React.useEffect(() => {
if(defaultCountryCode) {
const countryCodeUpper = defaultCountryCode.toUpperCase()
setCountryCode(countryCodeUpper)
}
},[defaultCountryCode])
return (
<PhoneInputWrapper>
<StyledPhoneInput
value={value}
onChange={_handleOnChange}
defaultCountry={countryCode}
onCountryChange={_handleOnCountryCodeChange} />
</PhoneInputWrapper>
)
}
我已經嘗試記錄newPhoneNumber
的值並且它按預期工作,除了當我更改值並關閉模式或嘗試保存它時,它記錄未定義並且我得到一個白屏。
您可能正在卸載執行一些 ajax 請求的組件,然后根據響應更新狀態。 在獲得響應之前組件已被卸載,但該功能繼續並嘗試更新不再安裝的組件的狀態。
處理此問題的適當方法是將請求存儲在某個數組中,這些數組將通過重新渲染持續存在(例如在 useRef 中)。 然后在組件卸載時,在 useEffect 清理函數中使用 Abort Controller API。
這篇文章可能對你有幫助: https : //medium.com/@selvaganesh93/how-to-clean-up-subscriptions-in-react-components-using-abortcontroller-72335f19b6f7
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.