在Promise的then方法中调用setState时,为何出现无法找到ID为104的元素错误?
setState in Promise.then What's Causing This?
This error pops up because React tries to update the DOM when the target element no longer exists. Promises run asynchronously—by the time your then callback fires, your component might have already been unmounted (like if the user navigated to another route, or a conditional render hid the component). But the component instance is still lingering, so calling setState makes React search for a DOM node that’s already gone, hence the frustrating error.
Solutions to Try
Here are a few reliable, React-friendly fixes:
Track component mount status before updating state
Use React’s lifecycle hooks to keep tabs on whether the component is still mounted. Only runsetStateif it’s safe to do so:Class component example:
class YourComponent extends React.Component { _isMounted = false; componentDidMount() { this._isMounted = true; yourAsyncPromise() .then(fetchedData => { // Only update state if the component is still attached to the DOM if (this._isMounted) { this.setState({ data: fetchedData }); } }); } componentWillUnmount() { // Mark component as unmounted when it's removed this._isMounted = false; } }Function component example:
import { useEffect, useState, useRef } from 'react'; function YourComponent() { const [data, setData] = useState(null); const isMounted = useRef(true); useEffect(() => { yourAsyncPromise() .then(fetchedData => { if (isMounted.current) { setData(fetchedData); } }); // Cleanup: flip the flag when component unmounts return () => { isMounted.current = false; }; }, []); return <div>{data && <p>{data}</p>}</div>; }Cancel async requests on unmount (for fetch-based promises)
If your Promise comes from afetchcall, useAbortControllerto cancel the request entirely when the component unmounts. This stops thethencallback from running at all:function YourComponent() { const [data, setData] = useState(null); useEffect(() => { const abortController = new AbortController(); const signal = abortController.signal; fetch('your-api-endpoint', { signal }) .then(response => response.json()) .then(fetchedData => setData(fetchedData)) .catch(error => { // Ignore intentional abort errors if (error.name !== 'AbortError') { console.error('Request failed:', error); } }); // Cancel the request when component is removed return () => abortController.abort(); }, []); return <div>{data && <p>{data}</p>}</div>; }Quick DOM element check (temporary workaround)
For quick debugging, you can manually verify if the target element exists before callingsetState:yourAsyncPromise() .then(fetchedData => { const targetElement = document.getElementById('104'); // Match the ID in your error if (targetElement) { this.setState({ data: fetchedData }); } });Note: This is a band-aid solution—stick to the first two methods for long-term fixes.
Wrap-Up
The core rule here is: only update state when the component’s DOM nodes are still present. The mount-status tracking and AbortController methods are standard React practices to avoid these DOM mismatch errors and prevent potential memory leaks.
内容的提问来源于stack exchange,提问作者S.M_Emamian

