<div id="root">
#root {
  display: flex;
  flex-direction: column;
}

.spinner-container {
  display: flex;
  align-items: center;
  justify-content: center;
}

.spinner {
  color: #000;
  display: inline-block;
  width: 20px;
  height: 20px;
  animation: spinner .75s linear infinite;
  border: 4px solid #000;
  border-bottom-color: transparent;
  border-radius: 100%;
  background: 0 0;
}

@keyframes spinner {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
import * as React from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import * as TypesReact from "https://cdn.skypack.dev/@types/react@17.0.2";
import * as TypesReactDom from "https://cdn.skypack.dev/@types/react-dom@17.0.1";

const Spinner: React.FC = () => {
  return (
    <div className="spinner-container">
      <span className="spinner"/>
    </div>
  )
}

const App: React.FC = () => {
  const [loading, setLoading] = React.useState<boolean>(true);
  const [todos, setTodos] = React.useState<any>();
  React.useEffect(async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/');
    const todos = await response.json();
    setTodos(todos);
    
    setTimeout(() => { setLoading(false); }, 1500);
  }, [])
  return loading ? <Spinner/> : <p>Hello, world! {todos.length} todos!</p>
}

ReactDOM.render(<App/>, document.getElementById("root"));
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js