React Timer using functional Hooks | Timer is not stopping - javascript

I want to create a time of 60s on react using hooks useState and useEffects This is what i am doing
import '../assets/css/timer.css'
import { useState, useEffect } from 'react'
const Timer = () =>{
const [ time, setTime ] = useState(0);
useEffect(()=>{
if(time!==60){
setInterval(()=>{
setTime(prevTime => prevTime+1) ;
}, 1000);
}
}, [])
return(
<>
<div className="circular">
<div className="inner"></div>
<div className="outer"></div>
<div className="numb">
{time} // Place where i am displaying time
</div>
<div className="circle">
<div className="dot">
<span></span>
</div>
<div className="bar left">
<div className="progress"></div>
</div>
<div className="bar right">
<div className="progress"></div>
</div>
</div>
</div>
</>
)
}
export default Timer
Timer is not stopping. It continues to go on for ever. I have tried this too
useEffect(()=>{
setInterval(()=>{
if(time!==60)
setTime(prevTime => prevTime+1) ;
}, 1000);
}, [])
Can some please explain where things are going wrong.

useEffect(..., []) will only run once, so time inside of it will never update. So you need to check prevTime inside of the setTime function, and then only increment if it's not 60. If it is, you should clear the interval, and then you should clear the interval in the cleanup of useEffect:
useEffect(()=>{
const i = setInterval(() => {
setTime(prevTime => {
if (prevTime !== 60) return prevTime+1;
clearInterval(i);
return prevTime;
});
}, 1000);
return () => clearInterval(i);
}, [])

You are close to having it working with your first attempt, but there are a few problems.
The main problem is that you pass an empty dependency array, meaning it will only run on the first render and not be updated on successive renders. Secondly you don't provide a return or 'clean up' meaning the interval is never cleared.
useEffect(() => {
if (time < 60) {
const timer = setInterval(() => {
setTime(prevTime => prevTime + 1);
}, 1000);
return () => clearInterval(timer);
}
}, [time])
Here we pass time in the dependency array and conditionally set the interval if time is less than your end time, 60 in your case but I shortened it to 5 so that you can see it stop. We also pass a return callback that will clear the interval at the end of each render cycle.
With this set up every time the setInterval updates the time state the useEffect will clear the interval at the end of the previous render, and then re-run in the current render setting the interval again if time is less than the limit.
The advantage of using the React render cycle this way, instead of clearing the interval in the interval callback, is that it gives you granular control of your timeout – allowing you to easily add further checks or extend/shorten the time based on other state values.
const { useState, useEffect } = React;
const Timer = () => {
const [time, setTime] = useState(0);
useEffect(() => {
if (time < 5) {
const timer = setInterval(() => {
setTime(prevTime => prevTime + 1);
}, 1000);
return () => clearInterval(timer);
}
}, [time])
return (
<div className="circular">
<div className="numb">
{time}
</div>
</div>
)
}
ReactDOM.render(
<Timer />,
document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

You have to clear setTimeout in Unmount state
for functional component
// Funtional component
useEffect(()=>{
const i = setInterval(() => {
setTime(prevTime => {
if (prevTime !== 60) return prevTime+1;
clearInterval(i);
return prevTime;
});
}, 1000);
return () => clearInterval(i);
}, [])
For class component
// Class component
componentWillUnmount() {
this.clearInterval()
}

Related

React setInterval and useState

I have 2 question. First, why this code does not work. Second, why this code slow when it comes 2^n -1 for example 1-3-7-15
let time = 0
function App() {
const [mytime, setMytime] = useState(time)
setInterval(() => {
time += 1
setMytime(time)
}, 1000)
return <div> {mytime} </div>
Issue
The setInterval gets called each time when mytime changes for rerendering (when you call the setMytime). And the number of setInterval calls grows exponentially. This would lead to a memory leak as well.
Solution
You should run it only once. You should use useEffect hook with an empty dependency array.
Try like this.
import { useEffect, useState } from "react";
function App() {
const [mytime, setMytime] = useState(0);
useEffect(() => {
// create a interval and get the id
const myInterval = setInterval(() => {
setMytime((prevTime) => prevTime + 1);
}, 1000);
// clear out the interval using the id when unmounting the component
return () => clearInterval(myInterval);
}, []);
return <div> {mytime} </div>;
}
export default App;

change the value of useState with setInterval

I have a simple component with useState that increase a counter in each click -
function Counter() {
let [counter, setCounter] = useState(0);
const incCounter = () => {
setCounter(counter + 1);
};
return (
<div className="App">
<h1>{counter}</h1>
<button onClick={incCounter}>Inc</button>
</div>
);
}
Here is its demo
and now I want to call the increase function each 1 second , so I added this piece of code into the component function -
useEffect(() => {
setInterval(() => {
incCounter();
}, 1000);
}, []);
Here is its demo
but I don't see the counter increased in the component.
How should I write it correctly and see the counter increased in each 1 second as expected ?
Issue
You've a stale enclosure of the state value from the render cycle the timer callback was set from.
Solution
Use a functional state update so the state is updated from the previous state, not the state from the render cycle the update was enqueued in. This allows the interval callback and click handler to seamlessly update state, independently from each other.
setCounter(counter => counter + 1);
In fact, you should use a functional state update anytime the next state value depends on any previous state value. Incrementing a counter is the classic example of using functional updates.
Don't forget to return a cleanup function to clear the interval for when the component umnounts.
Full code
function Counter() {
let [counter, setCounter] = useState(0);
const incCounter = () => {
setCounter((counter) => counter + 1);
};
useEffect(() => {
const timerId = setInterval(() => {
incCounter();
}, 1000);
return () => clearInterval(timerId);
}, []);
return (
<div className="App">
<h1>{counter}</h1>
<button onClick={incCounter}>Inc</button>
</div>
);
}
Demo

State within useEffect not updating

I'm currently building a timer in ReactJS for practice. Currently I have two components, a Timer component which displays the time as well as sets an interval upon mounting. I also have an App component which keeps tracks of the main state, such as state for whether the timer is paused as well as the current value of the timer.
My goal is to make it so that when I click the pause button, the timer stops incrementing. Currently I've tried to achieve this by using:
if(!paused)
tick(time => time+1);
which in my mind, should only increment the time state when paused is false. However, when I update the paused state by clicking on my button, this paused state inside the setTimeout does not change. My guess that setTimeout is forming a closure over the paused state, so it's not updating when the state changes. I tried adding paused as a dependency to useEffect but this caused multiple timeouts to be queued whenever paused changed.
const {useState, useEffect} = React;
const Timer = ({time, paused, tick}) => {
useEffect(() => {
const timer = setInterval(() => {
if(!paused) // `paused` doesn't change?
tick(time => time+1);
}, 1000);
}, []);
return <p>{time}s</p>
}
const App = () => {
const [time, setTime] = useState(0);
const [paused, setPaused] = useState(false);
const togglePaused = () => setPaused(paused => !paused);
return (
<div>
<Timer paused={paused} time={time} tick={setTime} />
<button onClick={togglePaused}>{paused ? 'Play' : 'Pause'}</button>
</div>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
So, my question is:
Why isn't my current code working (why is paused not updating within useEffect)?
Is there any way to make the above code work so that I can "pause" my interval which is set within the useEffect()?
To stop the timer return the function clearing the interval from useEffect().
React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.
(source: Using the Effect Hook - Effects with Cleanup)
You should also pass the paused in dependencies array to stop useEffect creating new intervals on each re-render. If you add [paused] it'll only create new interval when paused change.
const {useState, useEffect} = React;
const Timer = ({time, paused, tick}) => {
useEffect(() => {
const timer = setInterval(() => {
if(!paused) // `paused` doesn't change?
tick(time => time+1);
}, 1000);
return () => clearInterval(timer);
}, [paused]);
return <p>{time}s</p>
}
const App = () => {
const [time, setTime] = useState(0);
const [paused, setPaused] = useState(false);
const togglePaused = () => setPaused(paused => !paused);
return (
<div>
<Timer paused={paused} time={time} tick={setTime} />
<button onClick={togglePaused}>{paused ? 'Play' : 'Pause'}</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The setInterval captures the paused value the first time, you'll need to remove the interval, recreate it everytime paused is changed.
You can check this article for more info: https://overreacted.io/making-setinterval-declarative-with-react-hooks
You can use Dan's useInterval hook. I can't explain it better than him why you should use this.
The hook looks like this.
function useInterval(callback, delay) {
const savedCallback = React.useRef();
// Remember the latest callback.
React.useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
React.useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
Then use it in your Timer component like this.
const Timer = ({ time, paused, tick }) => {
useInterval(() => {
if (!paused) tick(time => time + 1);
}, 1000);
return <p>{time}s</p>;
};
I believe the difference is that useInterval hook is aware of its dependencies (paused) while setInterval isn't.

How make react countdown timer

i'm trying to do countdown timer with react. It will be basically countdown from 10 to 0 and when 0 i will call some function.
i found ideally for me some example: https://codesandbox.io/s/0q453m77nw?from-embed
but it's a class component i wan't to do that with functional component and hooks but i can't.
i tried:
function App() {
const [seconds, setSeconds] = useState(10);
useEffect(() => {
setSeconds(setInterval(seconds, 1000));
}, []);
useEffect(() => {
tick();
});
function tick() {
if (seconds > 0) {
setSeconds(seconds - 1)
} else {
clearInterval(seconds);
}
}
return (
<div className="App">
<div
{seconds}
</div>
</div>
);
}
export default App;
it's count down from 10 to 0 very quickly not in 10 seconds.
where i mistake ?
It appears the multiple useEffect hooks are causing the countdown to run more than once per second.
Here's a simplified solution, where we check the seconds in the useEffect hook and either:
Use setTimeout to update seconds after 1 second, or
Do something else (the function you want to call at the end of the countdown)
There are some downsides to this method, see below.
function App() {
const [seconds, setSeconds] = React.useState(10);
React.useEffect(() => {
if (seconds > 0) {
setTimeout(() => setSeconds(seconds - 1), 1000);
} else {
setSeconds('BOOOOM!');
}
});
return (
<div className="App">
<div>
{seconds}
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Downsides
Using setInterval has the downside that it could be stopped - for example, the component is unmounted, you navigate to a different tab, or close your computer. If the timer requires more robustness, the better alternative would be to store an endTime in the state (like a global store or context) and have your component check the current time against the endTime to calculate the countdown.
Do you care about precision? If so, you don't want setInterval. If you don't care about precision (and you probably don't) then you can schedule a call to tick() on an interval, not the other way around.
const TimeoutComponent extends Component {
constructor(props) {
super(props);
this.state = { countdown: 10 };
this.timer = setInterval(() => this.tick(), props.timeout || 10000);
}
tick() {
const current = this.state.countdown;
if (current === 0) {
this.transition();
} else {
this.setState({ countdown: current - 1 });
}
}
transition() {
clearInterval(this.timer);
// do something else here, presumably.
}
render() {
return <div className="timer">{this.state.countDown}</div>;
}
}
This depends on your logic a little bit. In the current situation your useEffect where you run your tick method is running on every render. You can find a naive example below.
function App() {
const [seconds, setSeconds] = useState(10);
const [done, setDone] = useState(false);
const foo = useRef();
useEffect(() => {
function tick() {
setSeconds(prevSeconds => prevSeconds - 1)
}
foo.current = setInterval(() => tick(), 1000)
}, []);
useEffect(() => {
if (seconds === 0) {
clearInterval(foo.current);
setDone(true);
}
}, [seconds])
return (
<div className="App">
{seconds}
{done && <p>Count down is done.</p>}
</div>
);
}
In the first effect we are doing the countdown. Using callback one for setting state since interval creates a closure. In the second effect we are checking our condition.
Simply use this snippet, As it will also help to memoize the timeout callback.
const [timer, setTimer] = useState(60);
const timeOutCallback = useCallback(() => setTimer(currTimer => currTimer - 1), []);
useEffect(() => {
timer > 0 && setTimeout(timeOutCallback, 1000);
}, [timer, timeOutCallback]);
console.log(timer);
Hope this will help you or somebody else.
Happy Coding!

Why setInterval with useState hook doesn't update state properly [duplicate]

I'm trying out the new React Hooks and have a Clock component with a time value which is supposed to increase every second. However, the value does not increase beyond one.
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
The reason is because the callback passed into setInterval's closure only accesses the time variable in the first render, it doesn't have access to the new time value in the subsequent render because the useEffect() is not invoked the second time.
time always has the value of 0 within the setInterval callback.
Like the setState you are familiar with, state hooks have two forms: one where it takes in the updated state, and the callback form which the current state is passed in. You should use the second form and read the latest state value within the setState callback to ensure that you have the latest state value before incrementing it.
Bonus: Alternative Approaches
Dan Abramov goes in-depth into the topic about using setInterval with hooks in his blog post and provides alternative ways around this issue. Highly recommend reading it!
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(prevTime => prevTime + 1); // <-- Change this line!
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
As others have pointed out, the problem is that useState is only called once (as deps = []) to set up the interval:
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => window.clearInterval(timer);
}, []);
Then, every time setInterval ticks, it will actually call setTime(time + 1), but time will always hold the value it had initially when the setInterval callback (closure) was defined.
You can use the alternative form of useState's setter and provide a callback rather than the actual value you want to set (just like with setState):
setTime(prevTime => prevTime + 1);
But I would encourage you to create your own useInterval hook so that you can DRY and simplify your code by using setInterval declaratively, as Dan Abramov suggests here in Making setInterval Declarative with React Hooks:
function useInterval(callback, delay) {
const intervalRef = React.useRef();
const callbackRef = React.useRef(callback);
// Remember the latest callback:
//
// Without this, if you change the callback, when setInterval ticks again, it
// will still call your old callback.
//
// If you add `callback` to useEffect's deps, it will work fine but the
// interval will be reset.
React.useEffect(() => {
callbackRef.current = callback;
}, [callback]);
// Set up the interval:
React.useEffect(() => {
if (typeof delay === 'number') {
intervalRef.current = window.setInterval(() => callbackRef.current(), delay);
// Clear interval if the components is unmounted or the delay changes:
return () => window.clearInterval(intervalRef.current);
}
}, [delay]);
// Returns a ref to the interval ID in case you want to clear it manually:
return intervalRef;
}
const Clock = () => {
const [time, setTime] = React.useState(0);
const [isPaused, setPaused] = React.useState(false);
const intervalRef = useInterval(() => {
if (time < 10) {
setTime(time + 1);
} else {
window.clearInterval(intervalRef.current);
}
}, isPaused ? null : 1000);
return (<React.Fragment>
<button onClick={ () => setPaused(prevIsPaused => !prevIsPaused) } disabled={ time === 10 }>
{ isPaused ? 'RESUME ⏳' : 'PAUSE 🚧' }
</button>
<p>{ time.toString().padStart(2, '0') }/10 sec.</p>
<p>setInterval { time === 10 ? 'stopped.' : 'running...' }</p>
</React.Fragment>);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
body,
button {
font-family: monospace;
}
body, p {
margin: 0;
}
p + p {
margin-top: 8px;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
button {
margin: 32px 0;
padding: 8px;
border: 2px solid black;
background: transparent;
cursor: pointer;
border-radius: 2px;
}
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
Apart from producing simpler and cleaner code, this allows you to pause (and clear) the interval automatically by simply passing delay = null and also returns the interval ID, in case you want to cancel it yourself manually (that's not covered in Dan's posts).
Actually, this could also be improved so that it doesn't restart the delay when unpaused, but I guess for most uses cases this is good enough.
If you are looking for a similar answer for setTimeout rather than setInterval, check this out: https://stackoverflow.com/a/59274757/3723993.
You can also find declarative version of setTimeout and setInterval, useTimeout and useInterval, a few additional hooks written in TypeScript in https://www.npmjs.com/package/#swyg/corre.
useEffect function is evaluated only once on component mount when empty input list is provided.
An alternative to setInterval is to set new interval with setTimeout each time the state is updated:
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = setTimeout(() => {
setTime(time + 1);
}, 1000);
return () => {
clearTimeout(timer);
};
}, [time]);
The performance impact of setTimeout is insignificant and can be generally ignored. Unless the component is time-sensitive to the point where newly set timeouts cause undesirable effects, both setInterval and setTimeout approaches are acceptable.
useRef can solve this problem, here is a similar component which increase the counter in every 1000ms
import { useState, useEffect, useRef } from "react";
export default function App() {
const initalState = 0;
const [count, setCount] = useState(initalState);
const counterRef = useRef(initalState);
useEffect(() => {
counterRef.current = count;
})
useEffect(() => {
setInterval(() => {
setCount(counterRef.current + 1);
}, 1000);
}, []);
return (
<div className="App">
<h1>The current count is:</h1>
<h2>{count}</h2>
</div>
);
}
and i think this article will help you about using interval for react hooks
An alternative solution would be to use useReducer, as it will always be passed the current state.
function Clock() {
const [time, dispatch] = React.useReducer((state = 0, action) => {
if (action.type === 'add') return state + 1
return state
});
React.useEffect(() => {
const timer = window.setInterval(() => {
dispatch({ type: 'add' });
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((seconds) => {
if (seconds === 5) {
setSeconds(0);
return clearInterval(interval);
}
return (seconds += 1);
});
}, 1000);
}, []);
Note: This will help to update and reset the counter with useState hook. seconds will stop after 5 seconds. Because first change setSecond value then stop timer with updated seconds within setInterval. as useEffect run once.
This solutions dont work for me because i need to get the variable and do some stuff not just update it.
I get a workaround to get the updated value of the hook with a promise
Eg:
async function getCurrentHookValue(setHookFunction) {
return new Promise((resolve) => {
setHookFunction(prev => {
resolve(prev)
return prev;
})
})
}
With this i can get the value inside the setInterval function like this
let dateFrom = await getCurrentHackValue(setSelectedDateFrom);
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time => time + 1);// **set callback function here**
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
Somehow similar issue, but when working with a state value which is an Object and is not updating.
I had some issue with that so I hope this may help someone.
We need to pass the older object merged with the new one
const [data, setData] = useState({key1: "val", key2: "val"});
useEffect(() => {
setData(...data, {key2: "new val", newKey: "another new"}); // --> Pass old object
}, []);
Do as below it works fine.
const [count , setCount] = useState(0);
async function increment(count,value) {
await setCount(count => count + 1);
}
//call increment function
increment(count);
I copied the code from this blog. All credits to the owner. https://overreacted.io/making-setinterval-declarative-with-react-hooks/
The only thing is that I adapted this React code to React Native code so if you are a react native coder just copy this and adapt it to what you want. Is very easy to adapt it!
import React, {useState, useEffect, useRef} from "react";
import {Text} from 'react-native';
function Counter() {
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest function.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
const [count, setCount] = useState(0);
useInterval(() => {
// Your custom logic here
setCount(count + 1);
}, 1000);
return <Text>{count}</Text>;
}
export default Counter;
const [loop, setLoop] = useState(0);
useEffect(() => {
setInterval(() => setLoop(Math.random()), 5000);
}, []);
useEffect(() => {
// DO SOMETHING...
}, [loop])
For those looking for a minimalist solution for:
Stop interval after N seconds, and
Be able to reset it multiple times again on button click.
(I am not a React expert by any means my coworker asked to help out, I wrote this up and thought someone else might find it useful.)
const [disabled, setDisabled] = useState(true)
const [inter, setInter] = useState(null)
const [seconds, setSeconds] = useState(0)
const startCounting = () => {
setSeconds(0)
setDisabled(true)
setInter(window.setInterval(() => {
setSeconds(seconds => seconds + 1)
}, 1000))
}
useEffect(() => {
startCounting()
}, [])
useEffect(() => {
if (seconds >= 3) {
setDisabled(false)
clearInterval(inter)
}
}, [seconds])
return (<button style = {{fontSize:'64px'}}
onClick={startCounting}
disabled = {disabled}>{seconds}</button>)
}
Tell React re-render when time changed.opt out
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => {
window.clearInterval(timer);
};
}, [time]);
return (
<div>Seconds: {time}</div>
);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>

Categories

Resources