admin管理员组

文章数量:1291146

For an example if we made a App ponent and we needed to create an element each time a button was clicked:

function App() {
  const handleClick = () => {
    // Code here
  }

  return (
    <div id="app">
      <button onClick={handleClick}>Click here</button>
    </div>
  )
}

Is it ok if i used document.createElement("div") and document.getElementById("app").append() in that case?

function App() {
  const handleClick = () => {
    let div = document.createElement("div")

    div.innerHTML = "Hi!"

    document.getElementById("app").append(div)
  }

  return (
    <div id="app">
      <button onClick={handleClick}>Click here</button>
    </div>
  )
}

For an example if we made a App ponent and we needed to create an element each time a button was clicked:

function App() {
  const handleClick = () => {
    // Code here
  }

  return (
    <div id="app">
      <button onClick={handleClick}>Click here</button>
    </div>
  )
}

Is it ok if i used document.createElement("div") and document.getElementById("app").append() in that case?

function App() {
  const handleClick = () => {
    let div = document.createElement("div")

    div.innerHTML = "Hi!"

    document.getElementById("app").append(div)
  }

  return (
    <div id="app">
      <button onClick={handleClick}>Click here</button>
    </div>
  )
}
Share Improve this question asked Jun 12, 2022 at 9:42 Random UserRandom User 131 silver badge6 bronze badges 1
  • 1 React uses vdom and synthetic events. So most of the time you should stay away from interacting with the Dom. – The Fool Commented Jun 12, 2022 at 9:52
Add a ment  | 

5 Answers 5

Reset to default 5

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 patible. 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 puted 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.

It's fine to use the document object for certain, limited things in React code,¹ but not in this case. That's not how you'd add an element to your #app div. Instead, you'd use state for it. When switching to an MVC/MVVM/whatever tool like React, you need to stop thinking in terms of modifying the DOM and start thinking in terms of ponent states.

In your case, for instance, you'd either want a boolean state member telling you whether to render that Hi! div, or perhaps an array state member of messages you might display.

Here's an example of the former:

const { useState } = React;

const App = () => {
    // The state information
    const [showHi, setShowHi] = useState(false);
    
    const handleClick = () => {
        // Set the state to true on button click
        setShowHi(true);
    };
    
    return <div>
        {/* Check the state and conditionally render */}
        {showHi && <div>Hi!</div>}
        <button onClick={handleClick}>Click here</button>
    </div>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare./ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

I suggest working through the tutorial on the React website for a solid introduction to React.


¹ A ment asked for examples of what's okay. A non-definitive list:

  • Mounting your React root or portal. (Of course. :-) )
  • If you need the current scroll offset in an effect or layout effect (document.documentElement.scrollTop).
  • If you need to look up and possibly manipulate elements that are outside the React tree(s) and can't or shouldn't be brought within the React tree(s) your code is managing. Usually this is when you're incrementally adding React to a codebase that otherwise does DOM manipulation directly (via the DOM itself, or a library like jQuery).

Yes, you can. But the React way to do this is to keep track of this in state. You can keep count of the number of divs you want to render, and update that. State update will trigger a rerender, and your view will be updated.

Below I am using a state variable count and initializing an Array using the Array() constructor of size equal to count.

function App() {
  const [count,setCount] = 0;
  const handleClick = () => {
    setCount(count => count+1);
  }

  return (
    <div id="app">
      <button onClick={handleClick}>Click here</button>
      {Array(count).map((x) => <div>{/**YOUR DIV CONTENT **/}<div>)}
    </div>
  )
}

If you need to access the DOM element, the remended approach is to use the useRef, useImperativeHandle, useLayoutEffect, or useid hooks, as these allow React to be aware of when you are using the DOM elements, and allows for future React updates to not break your existing behavior. In your example though, I would argue that you do not need access to the DOM element, and that you should instead can let React handle the rendering of the element via declarative JSX.

You don't you document.getElementById in reactjs

All point of react is to use jsx (dynamic HTML)

What you can to it's to create an array that you append item to this array each click and use map to render the new item each time :

        function App() {
        const [items,setItems] = useState([])
          const handleClick = () => {
            // Code here
    setItems(prev => {
    let arr = []
    //change obj each time to your need.
    let obj = {label : "test" , value : "test"}
    arr.push(obj)
    setItems(arr)
    })
          }
        
          return (
            <div id="app">
              <button onClick={handleClick}>Click here</button>
        {items.map((item,index) =>{
        return <p key={index}>{item.label}</p>
        })
            </div>
          )
        }

本文标签: javascriptCan i use the document object in ReactStack Overflow