Why I'm not able to clear my setInterval? - javascript

I'm trying to create an automatic counter when the component(Home here for instance) renders in the view. The counter should start at 1 and stop at 10. But I'm not able to clear my setInterval at 10. The counter remains incrementing.
What is the problem?
Thanks a lot.
export const Home = () => {
const [counter, setCounter] = useState(1)
let timer = useRef()
const animate = () => {
if(counter === 10){
clearInterval(timer.current)
}else{
setCounter((previous) => previous + 1)
}
}
useEffect(() => {
timer.current = window.setInterval(() => {
animate()
}, 900)
}, [])
return (
<div style={{textAlign: "center"}}>
<h1>{counter}</h1>
</div>
)
}

Problem is the closure of animate function over the initial value of counter, i.e. 1. As a result, the condition counter === 10 never evaluates to true.
This is why you should never lie about the dependencies of the useEffect hook. Doing so can lead you to bugs because of closures over the stale values from the previous renders of your component.
Solution
You can get rid of animate() function and write the logic inside the useEffect hook.
function App() {
const [counter, setCounter] = React.useState(1);
const counterRef = React.useRef(counter);
React.useEffect(() => {
const id = setInterval(() => {
// if "counter" is 10, stop the interval
if (counterRef.current === 10) {
clearInterval(id);
} else {
// update the "counter" and "counterRef"
setCounter((prevCounter) => {
counterRef.current = ++prevCounter;
return prevCounter;
});
}
}, 900);
// clearn interval on unmount
return () => clearInterval(id);
}, []);
return (
<div style={{ textAlign: "center" }}>
<h1>{counter}</h1>
</div>
);
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

I'd create a second useEffect() for clearing the interval:
const { useEffect, useRef, useState } = React;
const Home = () => {
const [counter, setCounter] = useState(1);
const timer = useRef();
useEffect(() => {
timer.current = setInterval(() => {
setCounter(x => x + 1);
}, 900);
// in case the component unmounts before the timer finishes
return () => clearInterval(timer.current);
}, []);
useEffect(() => {
if (counter === 10) {
clearInterval(timer.current);
}
}, [counter]);
return (
<div style={{ textAlign: 'center' }}>
<h1>{counter}</h1>
</div>
);
}
ReactDOM.render(<Home/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

That's because modifying ref.current doesn't trigger a rerender.
You need to use useEffect to clear it.
const animate = () => {
setCounter((previous) => previous + 1);
};
useEffect(() => {
if (counter === 10) clearInterval(timer.current);
}, [counter]);

Related

Unable to get updated props in setInterval React functional component

I am unable to get the updated prop in setInterval inside Component1, it gives me the old value
following is the code I am using:
import { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
const intervalID = setInterval(() => {
setCounter((counter) => counter + 1);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Component1 counter={counter} />
</div>
);
}
const Component1 = ({ counter }) => {
useEffect(() => {
const intervalID = setInterval(() => {
console.log(counter);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
return <h1>Component1 count: {counter}</h1>;
};
In this code inside Component1, the counter's value is updated after every second on the browser, but on the console.log inside setInterval, I am always getting the initial value not the updated one.
I also get a solution which looks like this
import { useState, useEffect, useRef } from "react";
import "./styles.css";
export default function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
const intervalID = setInterval(() => {
setCounter((counter) => counter + 1);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Component1 counter={counter} />
</div>
);
}
const Component1 = ({ counter }) => {
const counterRef = useRef(null);
counterRef.current = counter;
useEffect(() => {
const intervalID = setInterval(() => {
console.log(counterRef.current);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
return <h1>Component1 count: {counter}</h1>;
};
But in this solution, I have to use extra memory space as I am creating a ref and assigning value to it.
Is there any better solution there to get updated value inside setInterval to this the correct way to do it.
You can try this one in scenario, where you face closure behavior of JavaScript,
useEffect(() => {
const intervalId = setInterval(() => {
console.log('count is', counter);
}, 1000);
return () => clearInterval(intervalId);
}, [counter]);
But in your scenario this will be more suitable in Component1,
useEffect(() => {
console.log(counter);
}, [counter]);
In this case : on first render you set an Interval that print 0 on Console every second
useEffect(() => {
const intervalID = setInterval(() => {
console.log(counter);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
I Edit your codes :
import { useState, useEffect } from "react";
export default function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
const intervalID = setInterval(() => {
setCounter((counter) => counter + 1);
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Component1 counter={counter} />
</div>
);
}
const Component1 = ({ counter }) => {
useEffect(() => {
console.log(counter);
}, [counter]);
return <h1>Component1 count: {counter}</h1>;
};
on this case in component1 : when value of counter changed, console.log print new value
useEffect(() => {
console.log(counter);
}, [counter]);
read about useEffect
If you want to execute a method when a property changes. you can use useEffect and you must pass that property in closure like below code :
useEffect(() => {
console.log(counter);
}, [counter]);
I pass counter to useEffect and when it changes, useEffect run console.log with new value

SetInterval on mount for a set duration

I have gone through some Q&As here but havent been able to understand what I am doing wrong. The following component prints 0s in console and does not update the DOM as expected.
const NotifPopup = ({ notif, index, closeHandler }) => {
const [timer, setTimer] = useState(0);
useEffect(() => {
const timerRef = setInterval(() => {
if (timer === 3) {
clearInterval(timerRef);
closeHandler(index);
} else {
console.log("timer", timer);
setTimer(timer + 1);
}
}, 1000);
}, []); // only run on mount
return (<div className="notifPopup">
<span className=""></span>
<p>{notif.message}</p>
<span className="absolute bottom-2 right-8 text-xs text-oldLace">{`closing in ${timer}s`}</span>
</div>);
};
Why is the setInterval printing a stream of 0s in console and not updating the DOM?
You are loggin, comparing, and setting a stale value due to closures.
See more use cases in a related question.
useEffect(() => {
// timerRef from useRef
timerRef.current = setInterval(() => {
setTimer((prevTimer) => prevTimer + 1);
}, 1000);
}, []);
useEffect(() => {
console.log("timer", timer);
if (timer === 3) {
clearInterval(timerRef.current);
}
}, [timer]);
Check out the code for useInterval in react-use. Inspecting the different hooks in this package can greatly improve your hooks understanding.
import { useEffect, useRef } from 'react';
const useInterval = (callback: Function, delay?: number | null) => {
const savedCallback = useRef<Function>(() => {});
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
if (delay !== null) {
const interval = setInterval(() => savedCallback.current(), delay || 0);
return () => clearInterval(interval);
}
return undefined;
}, [delay]);
};
export default useInterval;
And the usage as described in the docs:
import * as React from 'react';
import {useInterval} from 'react-use';
const Demo = () => {
const [count, setCount] = React.useState(0);
const [delay, setDelay] = React.useState(1000);
const [isRunning, toggleIsRunning] = useBoolean(true);
useInterval(
() => {
setCount(count + 1);
},
isRunning ? delay : null
);
return (
<div>
<div>
delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
</div>
<h1>count: {count}</h1>
<div>
<button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
</div>
</div>
);
};
To start the interval on mount simply change the value of isRunning on mount:
useMount(()=>{
toggleIsRunning(true);
});

Re-render text on React

I'm developing a React (Next.js) app that contains a counter regressive (10 seconds), I have this code:
let [time, setTime] = useState(10);
setTime = () => {
setTimeout(() => {
if (time > 0) {
console.log(time);
time -= 1;
setTime();
}
else {
console.log("end");
}
}, 1000);
};
setTime();
Then:
return (
<>
<span>{time}</span>
</>
)
Ok, that works fine on console, print 10, then 9, then 8, and so on until it reaches 0, but the tag <span> keep showing 10 (the initial value).
Thanks, and hope you can help me!
The issue is how you are using the state hook. You are modifying the time value, and you are mutating it inside the setTimeout closure. Please check out how state should be handled: https://reactjs.org/docs/hooks-state.html.
const [time, setTime] = useState(10);
// somewhere else
setTime(time => time - 1)
Use should use setState to update the state
Try this
class App extends React.Component {
state = {
time: 10,
};
setTime = () => {
setTimeout(() => {
if (this.state.time > 0) {
console.log(this.state.time);
this.setState((prev) => ({ time: prev.time - 1 }));
this.setTime();
} else {
console.log("end");
}
}, 1000);
};
render() {
return (
<div className="App">
<span>{this.state.time}</span>
<br />
<br />
<button onClick={this.setTime}>Start counter</button>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
maybe you could try usEffect hook: https://reactjs.org/docs/hooks-effect.html
useful to handle side effects in your component
import { useState, useEffect } from "react";
export default function App() {
let [time, setTime] = useState(10);
useEffect(() => {
setTimeout(() => {
setTime((time) => time - 1);
}, 1000);
});
return <span>{time}</span>;
}
SandBox: https://codesandbox.io/s/dreamy-swanson-heiec?file=/src/App.js

Unable to access counter after gets updated

I want to start an interval by clicking on a button.
Here the interval gets started but, I can't access the value of counter. because when counter gets equal to 5, the interval should be stoped.
Here is the example:
let interval = null;
const stateReducer = (state, value) => value;
function App(props) {
const [counter, setCounter] = useReducer(stateReducer, 0);
const increment = () => {
interval = setInterval(() => {
setCounter(counter + 1);
if (counter === 5) clearInterval(interval);
console.log(counter);
}, 1000);
};
return (
<div>
<p>{counter}</p>
<button className="App" onClick={increment}>
Increment
</button>
</div>
);
}
You can run this code on codesandbox
change const stateReducer = (state, value) => value; to const
stateReducer = (state, value) => state+value;
make a variable let current_counter = 0; outside function
Change your increment function like this
current_counter = counter;
const increment = () => {
interval = setInterval(() => {
setCounter(1);
if (current_counter === 5) clearInterval(interval);
console.log(current_counter);
}, 1000);
};
Done
import React, { useReducer, useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
let interval = null;
let current_counter = 0;
const stateReducer = (state, value) => value;
function App(props) {
const [status, setStatus] = useState(false);
const [counter, setCounter] = useReducer(stateReducer, 0);
useEffect(()=>{
if(status){
const interval = setInterval(() => {
setCounter(counter + 1);
}, 1000)
return ()=>{
clearInterval(interval)
};
}
})
const increment = () => {
setStatus(!status)
};
return (
<div>
<p>{counter}</p>
<button className="App" onClick={increment}>
Increment
</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Your code has a few problems.
Your reducer declaration
const initialState = { value : 0 }
const reducer = (state, action) =>{
if(action.type === 'INCREMENT') return { value : state.value + 1 }
return state
}
How you're setting your reducer
const [state, dispatch] = useReducer(reducer, initialState)
How you're dispatching your action
intervals are imperative code, you can't consistently declare an interval inside a React's handler without worrying about closure. You could use the click only to flag that the interval should start and handle all imperative code inside an useEffect. Here is a working example
const initialState = { value: 0 };
const reducer = (state, action) => {
if (action.type === "INCREMENT")
return {
value: state.value + 1
};
};
function App() {
const [state, dispatch] = React.useReducer(reducer, initialState);
const [clicked, setClicked] = React.useState(false);
useEffect(() => {
let interval = null;
if (clicked) {
interval = setInterval(() => {
dispatch({ type: "INCREMENT" });
}, 1000);
}
if (state.value > 4) clearInterval(interval);
return () => clearInterval(interval);
}, [clicked, state]);
return <button onClick={() => setClicked(true)}>{state.value}</button>;
}
If your curious about closures and how react handle imperative code take a look on this awesome article from Dan Abramov (the most detailed explanation about effects out there).

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