简体   繁体   中英

input onChange is wiping all elements from DOM in React. The input form works well with a button, but can't seem to work onChange on the first load

So I'm creating a grid that you can resize using two input fields on the app. I have the input for cells across, input for cells down and the button to set the grid which works nicely. I want to change so that the input updates the state stored on cellsAcross and cellsDown. When I remove the button and add the onChange attribute to the input elements, it works if I don't refresh the browser, but as soon as everything renders for the first time, when adding an input everything in the DOM disappears.

Here's the code with the button:

 function App() { const [cellsAcross, setCellsAcross] = useState(5); const [cellsDown, setCellsDown] = useState(5); const getGridSize = () => { const inputAcross = document.getElementById("cells-across").value; const cellsAcross = parseInt(inputAcross); setCellsAcross(cellsAcross); const inputDown = document.getElementById("cells-down").value; const cellsDown = parseInt(inputDown); setCellsDown(cellsDown); console.log(`Across: ${cellsAcross} | Down: ${cellsDown}`); }; return ( <div className="app"> <Header /> <CellGrid numberOfColumns={cellsAcross} numberOfRows={cellsDown} /> <label htmlFor="cells-across">Across</label> <input type="number" id="cells-across" name="cells-across" min="1" /> <br /> <label htmlFor="boxes-down">Down (1-20):</label> <input type="number" id="cells-down" name="cells-down" min="1" /> <br /> <button onClick={getGridSize}>Make Grid</button> <br /> </div> ); } export default App;

And this is what I want it to be:

 import React, { useState } from "react"; import CellGrid from "./CellGrid"; import "./App.css"; import Header from "./Header"; function App() { const [cellsAcross, setCellsAcross] = useState(5); const [cellsDown, setCellsDown] = useState(5); const getGridSize = () => { const inputAcross = document.getElementById("cells-across").value; const cellsAcross = parseInt(inputAcross); setCellsAcross(cellsAcross); const inputDown = document.getElementById("cells-down").value; const cellsDown = parseInt(inputDown); setCellsDown(cellsDown); console.log(`Across: ${cellsAcross} | Down: ${cellsDown}`); }; return ( <div className="app"> <Header /> <CellGrid numberOfColumns={cellsAcross} numberOfRows={cellsDown} /> <label htmlFor="cells-across">Across</label> <input type="number" id="cells-across" name="cells-across" min="1" onChange={getGridSize} /> <br /> <label htmlFor="boxes-down">Down (1-20):</label> <input type="number" id="cells-down" name="cells-down" min="1" onChange={getGridSize} /> </div> ); } export default App;

Update onChange={()=>{setCellsAcross(e.target.valeu)}} to just set the state value to the new value. That will cause the entire component to re-render.

Related - it's bad practice to pull values out of the DOM directly. If you really wanted to do get the value of that input elsewhere in code, you'd add a const myCellsAcrossRef=useRef() and then add a ref attribute to the element: ref={myCellsAcrossRef}`.

Finally, you don't need your getGridSize() method if you just set the across & down values onChange, but if you did... you'd name it "setGridSize() or updateGridSize()" to indicate the method changes things. "Get" implies the function will not have side effects/mutations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM