Requirements:
1) React functional component.
2) It should just return loading text: "Loading".
3) Show the dots being added incrementally ( 1) to the end of the loading text every second.
For example:
Loading. -1s- Loading.. -1s- Loading... -1s- Loading
Decide the static elements. Then add the dynamics (states, hooks etc). As per the thinking in React doc.
1) Create a functional component that returns "Loading".
const Loading = () => { const loadingText = "Loading"; return ( <div> <h2>{loadingText}</h2> </div> ); }; export default Loading;
1) The number of dots represents a state of the component. So, define a state variable using useState.
const [dots, setDots] = useState(1);
And add the dots after loading text
{".".repeat(dots)}
2) A state changes automatically after each second. window.setInterval can perform this task. Leave the callback function empty for now.
window.setInterval(() => { // Logic to increment dots }, 1000);
3) Create a useEffect hook that only runs once after initial render.
useEffect(() => { window.setInterval(() => { // Logic to increment dots }, 1000); }, []);
Till now, the app only shows "Loading.".
Take a pause and think of the logic inside window.setInterval callback function.
The obvious looking solution:
setDots((dots + 1) % 4);
However, it is wrong. The component will only go from
"Loading."-1s-"Loading..". Then it will get stuck.
Reason: The useEffect's callback fn is triggered on the initial state of the dots (1). Any update in dots variable does not affect the closure of useEffect's callback fn.
Catch-1: Including dots in the dependency array of useEffect does not make sense. Because then it calls the window.setInterval on each update of the dots state. (Can use window.setTimeout instead. But why?)
Catch-2: The Loading component's dots state should be dependent on the useEffect and window.setInterval. However, using dots directly in the useEffect makes the useEffect depend upon it.
Before going to the next step, think about Closures.
Define useEffect's callback's own dots state (say effectDots). The window.setInterval's callback function increments the effectDots and also sets the Loading Component's dots state.
(The key is to alter the dependency from setInterval -> component's dots state to component's dots state -> setInterval. )
Revised version of callback functions of useEffect and window.setInterval with a local state effectDots:
useEffect(() => { let effectDots = 1; window.setInterval(() => { // increment, modulo 4 // set the Loading component's state setDots(effectDots++ % 4); }, 1000); }, []);
The above is the detailed content of Implementing a basic loading state. For more information, please follow other related articles on the PHP Chinese website!