Home > Software engineering >  how to add an element by clicking action in React?
how to add an element by clicking action in React?

Time:02-24

I'm creating a simple logic here. If one click an element from left-side box, the element will be deleted and added to right-box. So, I create this functions

function deleteElement(e: any){
const clickedElement = e.target
  clickedElement.remove()
  const addedElement = <div onClick={addedItem}><input type="checkbox" className="fruits" value="apple" id="apple" /><label htmlFor="apple" className="fruit-name">Apple</label></div>
  const rightBox = document.getElementById("rightBox")
  rightBox?.appendChild(addedElement)
  console.log("The Element Has Been Added To Your Cart.");
}

but react/ts says

Argument of type 'Element' is not assignable to parameter of type 'Node'. Type 'ReactElement<any, any>' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 46 more

So, type "Element" is not assignable to parameter of type 'node' ← this means appendChild is node system, right? then How should I add any element in right-box??

CodePudding user response:

You should be storing the children of the box as a state:

const [boxChildren, setBoxChildren] = useState([]);

return (
    <div>
        {boxChildren}
    </div>
);

Then to add/delete on click (element is something like <div></div>):

setBoxChildren([...boxChildren, element]); // .push

setBoxChildren([element, ...boxChildren]); // .unshift

setBoxChildren(boxChildren.slice(0, -1)); // .pop

setBoxChildren(boxChildren.slice(1)); // .shift

So for example, click the button to add elements:

function App() {
  const [boxChildren, setBoxChildren] = React.useState([]);

  return (
      <div>
          <button onClick={
              () => setBoxChildren([...boxChildren, <div>hello</div>])
          }>add</button>
          {boxChildren}
      </div>
  );
}

ReactDOM.render(<App />, document.body);
<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>

CodePudding user response:

I strongly suggest to not inject html in react in this way.

You should find a more react-compliant way like create a state variable and conditional render html:

import React, { useState } from 'react';

function myComponent = () => {
   const [position, setPosition] = useState("left");

   const addedItem = (newPos) => {
       setPosition(newPos);
   } 
  
   return (
     <div>
        <LeftBox>{position === "left" && <div onClick={() => addedItem("right")}><input type="checkbox" className="fruits" value="apple" id="apple" /><label htmlFor="apple" className="fruit-name">Apple</label></div>}</LeftBox>
        <RightBox>{position === "right" && <div onClick={() => addedItem("left")}><input type="checkbox" className="fruits" value="apple" id="apple" /><label htmlFor="apple" className="fruit-name">Apple</label></div>}</RightBox>
     </div>
   );
}

export default myComponent;

In this example, every time you click div, checkbox will be rendered from an hypotetical component rendered on left side (I called it LeftBox) to another hypotetical component rendered on right side (I called it RightBox).

  • Related