Can you?
You can, but this goes against the idea of React in the first place and is advised against. Updating the DOM this way can cost you performance and even introduce bugs in your code.
The point of React is to handle updating the DOM in a performant way that is cross-browser compatible. In fact, behind the scenes, React is going to create the <div>
element and place it in the DOM, but it is going to do so in a less costly and better-managed way by using a virtual representation of the DOM and everything in it. This is not as expensive as directly building, destroying and rebuilding elements on the page, because, for one, not everything on the page needs to be changed each time a user interaction that changes something of the page happens. React will react to parts of the page that have changed and keep parts that have not changed improving the performance on your web app. (See
Reactive Updates), This is one of the reasons the React library was built.
React keeps its own internal registry of elements it renders on the page, in the virtual DOM. It updates and tracks them all through their lifecycle on the page. Because of this, it knows which elements to replace, keep or tear down during user interaction. So creating an element by using the document
object directly circumvents the creation (and registration) of a representation of the element in the virtual DOM making React unaware of the element - leaving the lifecycle handling of the element to the browser.
The React way
Because of the above, anything that has to do with the UI; including rendering, updating and destroying is best left to React.
The way to build (thanks to JSX and this is an improvement to @yanir's answer) your element is by simply writing out the element where you need it (or storing it in a variable first and using embedded JSX). The innerHTML
attribute can be an embedded expression that is computed in the div
element. Don't worry, this operation won't cost as much as using the document
object to create elements directly. We'll just need a form of state to track how many times the user has clicked and create a plain JavaScript object then use the map()
method to create as many <div>
s as needed.
function App() {
const [items, setItems] = useState([]);
const handleClick = () => {
let obj = { value: "Hi!" };
setItems([...items, obj]);
};
return (
<div id="app">
<button onClick={handleClick}>Click here</button>
{items.map((item, index) => {
return <div key={index}>{item.value}</div>;
})}
</div>
)
}
If you need to interact with the DOM directly, through the document
object for example, as @Kaushik suggested, you can track the element through the use of hooks like useRef()
, to get a reference to the object, useId()
for unique stable Ids across server and client, useLayoutEffect()
to hook into the browser after DOM updates but before it paints and so on. That being said, there are some APIs and attributes that you may need to access from the document
object like events, title
, URL
, and several other attributes. In as much, as these do not mutate the UI, you can use these when needed, while the UI operations are left to React to handle.