here's my problem. I have a premade component, which is a "line" of content, which contains some buttons and some input boxes. Now, i want to add more of this exact component, whenever i press a button "add row", but i have no clue on how i can do this. I know basic concepts like States, map ... but i don't know ho to put it on code. Can someone explain me how can i do it ?
PS I'm really new to React, and in general to JS world
Here's the code
App.js
import React, { useState } from "react";
import "./App.css";
import OpLine from "./Components/OpLine";
function App() {
const addRowHandler = () => {
};
return (
<div>
<div className="bg">
<button onClick={addRowHandler}> Add Row </button>
<OpLine></OpLine>
<div className="result">Result is : (resVar) </div>
</div>
</div>
);
}
export default App;
OpLine.js
import React from "react";
import Card from "./Card/Card";
import './OpLine.css';
import OpForm from "./OpForm/OpForm";
const OpLine = () => {
return(
<Card className="line">
<OpForm></OpForm>
</Card>
);
};
export default OpLine;
OpForm.js
import React from "react";
import "./OpForm.css";
const OpForm = () => {
return (
<div className="op-form">
{/*div handling op button*/}
<div className="operando">
<label>Operando</label>
<select>
<option> </option>
<option>-</option>
</select>
</div>
{/*div handling number input button */}
<div className="number-input">
<label>Insert number</label>
<input type="number"></input>
</div>
<button>Delete</button>
<button>Disable</button>
</div>
);
};
export default OpForm;
CodePudding user response:
Not sure if this fits your needs, but you can create a counter inside the state and iterate this in order to render the components.
Button will increment the counter
const [counter, setCounter] = useState(1);
const addRowHandler = () => {
setCounter(counter 1);
};
and in render method
{Array.from({length: counter}).map(() => <OpForm></OpForm>)}
CodePudding user response:
Instead of thinking about it as "adding a component" think of it as "updating state". The state then informs the main component how to render it.
Here's a small example where I'm using name, age, and role as property names. After you've added a couple of rows, and filled in some information, click the "Show state" to see the result.
const { useState } = React;
function Example() {
// Initialise the state as an empty array
const [ state, setState ] = useState([]);
// When the `addRow` button is clicked, add a new
// empty object to the state
function addRow(e) {
const object = { name: '', age: '', role: '' };
setState([...state, object]);
}
// We pass this handler down to the Row component
function handleChange(e) {
// Check to see if the element that's changed
// is an input
if (e.target.matches('input')) {
// Get the id from the div dataset
const { id } = e.currentTarget.dataset;
// Get the name and value from the changed element
const { name, value } = e.target;
// Copy the state
const copy = [...state];
// Create a new object using the object in state
// at index === id, and update the correct property
const obj = { ...state[id], [name]: value };
// Add that object to the state copy
copy[id] = obj;
// Finally update the state
setState(copy);
}
}
// We now create some rows by mapping
// over the data and returning an array
// of components which have an id based
// on their position in the state array, some
// data contained in the object, and the handler
function createRows(state) {
return state.map((obj, i) => {
return (
<Row
id={i}
data={obj}
handleChange={handleChange}
/>
);
});
}
// Small function to show state when a
// button is clicked
function showState() {
console.log(JSON.stringify(state));
}
// Check to see if state has length, and then
// create the rows
return (
<div>
<button onClick={addRow}>Add a row</button>
<button onClick={showState}>Show state</button>
{state.length ? createRows(state) : <div />}
</div>
);
}
// Row accepts and id, some data, and the handler
function Row({ id, data, handleChange }) {
// Destructure the information from `data`
const { name, age, role } = data;
// Build the Row JSX. Note that we add the
// id as a data attribute on the div element
return (
<div
data-id={id}
className="row"
onChange={handleChange}
>
<label>Name
<input name="name" value={name} />
</label>
<label>Age
<input name="age" value={age} />
</label>
<label>Role
<input name="role" value={role} />
</label>
</div>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
input { margin-left: 0.5em; display: inline-block;}
.row { background-color: #efefef; padding: 0.3em; margin-top: 1em; }
button { margin-right: 0.5em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>