Requests should be executed in a way that doesn't block the user interface from displaying, ensuring the application remains responsive while waiting for data
It's a good practice to initiate a visual indicator, such as an animation or so-called skeleton elements, during loading.
Hence, it's worthwhile to trigger API requests when the component has already rendered, the application is responsive, and there's an element indicating ongoing loading.
Class Components
Requests to an external API should be performed in the componentDidMount
method.
class MyComponent extends Component<never, State> { componentDidMount = async () => { this.setState({ isLoading: true }); await fetchData(...); this.setState({ isLoading: false }); }; render = () => { return ( <> {this.state.isLoading ? <div>Waiting...</div> : <div>Hello World!</div>} </> ); }; }
Functional Components
The useEffect
hook is the place to handle side effects. It's crucial to ensure it doesn't execute every time the component re-renders to avoid unnecessary requests and rerenders:
const MyComponent: FC = () => { const [isLoading, setIsLoading] = useState(); const fetchFunction = useCallback(async () => { setIsLoading(true); await fetchData(...); setIsLoading(false); }, []); useEffect(() => { fetchFunction(); }, [fetchFunction]); return ( <> {isLoading ? <div>Waiting...</div> : <div>Hello World!</div>} </> ); }