Add component from a function on button click - reactjs

I want to dynamically add component every time a button is clicked. But I can't figure it out myself, and most answers I found online are class based.
This is what I wrote: I want to pass a component and a name props every time the button is clicked.
import List from "./List";
function App() {
let listCount = 0;
const extraList = () => {
listCount++;
return(
<List name={`list-{listCount}`} />
);
};
return (
<div>
<button onClick={extraList}>Add List</button>
</div>
);
}
export default App;

You can use useState
function App() {
const [listCount, setListCount] = useState(0);
const extraList = () => {
setListCount(listCount + 1);
};
return (
<div>
{Array.from({ length: listCount }, (_, i) => i + 1).map((i) => (
<List name={`list-${i}`} />
))}
<button onClick={extraList}>Add List</button>
</div>
);
}

Related

Unable to pass a function as a prop to child component in React

I'm trying to pass a function (addTask) as a prop from parent component (MainComponent.js) to Child Component (Button.js) but it's not working. I've also passed a variable (btnColor) as prop and it's working properly. What am I missing?
MainComponent.js:
import Button from "./Button";
const MainComponent = () => {
const addTask = () => {
console.log("Task Added...");
};
return (
<div>
<div> Header Component here </div>
<div> Some Data </div>
<Button onClick={addTask} btnColor="red" />
<div> Footer Component here </div>
</div>
);
};
export default MainComponent;
Button.js:
const Button = ({ addTask, btnColor }) => {
return (
<button style={{ backgroundColor: btnColor }} onClick={addTask}>
Add
</button>
);
};
export default Button;
I'm expecting the console to log 'Task Added...' but it isn't logging anything.
You're not passing it through correctly. You're passing it to onClick whereas you want to pass it through as addTask
Incorrect: <Button onClick={addTask} btnColor="red" />
Correct: <Button addTask={addTask} btnColor="red" />
I think it should be like this
const MainComponent = () => {
const addTask = () => {
console.log('Added new task...')
}
return (
<Button addTask={addTask} />
)
}
const Button = ({ addTask }) => {
return (
<button onClick={addTask} ></button>
)
}

How to make children clicked when clicking parent

How can I make children clicked when clicking parent?
My component is like this
const AllForms = ({ data }) => {
const divclick = ()=>{
// click all the buttons inside the div
}
const populateFormidButton = () => {
return data.subs.map((i, index) => {
return (
<button key={index} type="submit" form={i.formId}></button>
)
})
}
return (
<div onClick={divclick}>
{populateFormidButton()}
</div>
)
}
export default AllForms
I want when I click the div all the buttons inside that div will be clicked too. How to do that?
I hope I understood the task correctly.
In this example I used useRef and querySelectorAll("button") and click()
import { useRef } from "react";
const Form = ({ data }) => {
const divReference = useRef(null);
const divclick = () => {
const buttonList = [...divReference.current.querySelectorAll("button")];
buttonList.forEach(el=>el.click());
};
const populateFormidButton = () => {
return data.subs.map((i, index) => {
return (
<button key={index} type="submit" form={i.formId}>
{i}
</button>
);
});
};
return (
<div
ref={divReference}
onClick={divclick}
>
{populateFormidButton()}
</div>
);
};
export default Form;

How can I change the background color of elements when they're clicked?

I have a list of div elements in a ReactJS projects. I want to just get an indication when someone clicks change the background color.
the following is the basic code.
function changetoselected(event){
// now change backgroundColor of
// event.currentTarget to white
}
<div>
bigarrayofsize100plus.map((item,index) =>{
return(
<div
className="p-2"
onClick={(e) => changetoselected(e)}
style={{backgroundColor:"green"}}
>
.....
</div>
)
}
</div>
I dont want to store in the state all the elemets uncessarily. I dont have to trace clicked items here.
If once clicks i want to just change color. How can i do it
Use the style property to set a backgroundColor like this.
function changetoSelected(event){
event.target.style.backgroundColor = '#fff'
}
You can also use Refs in React like this
For a Function Component do this
`
import { useRef } from 'react';
function MyComponent() {
const divEl = useRef(null);
const changeToSelected = () => {
divEl.current.style.backgroundColor = '#fff';
};
return (
<div ref={divEl} onClick={changeToSelected}>
...
</div>
);
}
For a Class Component do this
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.divElement = React.createRef();
}
changetoselected = () => {
this.divElement.current.style.backgroundColor = '#fff';
}
render() {
return <div ref={this.divElement} onClick={this.changetoselected}>
...
</div>;
}
}
After all, working with pure dom (by ref or event) may not be what you are searching for, you can consider using react state and apply className or style to your dom elements
import { useState } from 'react';
const MyComponent = () => {
const [backgroundColor, setBackgroundColor] = useState('green');
return (
<div
onClick={() => setBackgroundColor('white')}
style={{ backgroundColor }}
>
...
</div>
);
}
EDIT
function MyComponent() {
const divEl = useRef(null);
const changeToSelected = () => {
divEl.current.style.backgroundColor = '#fff';
};
return (
<div>
{bigarrayofsize100plus.map((item,index) =>
<ChildComp
key={index}
item={item}
>
.....
</div>
)}
</div>
);
}
function ChildComp({ item }) {
const divEl = useRef(null);
const changeToSelected = () => {
divEl.current.style.backgroundColor = '#fff';
};
return (
<div
ref={divEl}
onClick={changeToSelected}
className="p-2"
style={{backgroundColor:"green"}}
>
// do stuff with item heere
</div>
);
}

import and export may only appear at the top level - reactjs

Good day Everyone,
I'm trying to run a query that increases a number whenever a button is clicked. I'm using a course from udemy is kinda old and our setup/installation is different. Please look at my code down below.
let count = 0;
const addOne = () => {
count++;
rendertheCounterApp();
};
const minus =() => {
console.log('Minus',);
}
const Reset = () => {
console.log ('Reset');
};
const rendertheCounterApp = () => {
const App = () => {
return (
<div className='App'>
<h1>Toggler {count} </h1>
<button onClick ={addOne}> +1 </button>
<button onClick={minus}>-1</button>
<button onClick ={Reset}>Rest</button>
</div>
);
};
export default App;
};
rendertheCounterApp();
is there any way I can modify that code to make the number increase whenever I click on the button?
Thanks in advance.
You need to have state to store the count and you can increase or decrease the count without creating any special functions. Try something like:
import React, { useState } from 'react';
const RenderTheCounterApp = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Add</button>
<button onClick={() => setCount(count - 1)}>Subtract</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};

How to use a useState function in another component with props?

I write a React.js note web application where a user can add up to 10 notes.
I use map() to iterate the array of notes, and a useState(1) hook to update its count (the default number of notes is 1), so I would like to do something like this:
{[...Array(noteCount)].map((_, i) => <Note onUpdateNoteCount={() =>setNoteCount(n => n - 1)} key={i} />)}
The thing is that the Note() component is inside a Main() component which is in the App() component, so I want to get the needed values as props of App(), and than use them in Note(), but can not figure out how and where to put it.
Thanks!
App.js
import React from 'react';
import Header from './Header';
import Main from './Main';
function App () {
const [noteCount, setNoteCount] = React.useState(1);
function multiplyNoteComponent () {
if (noteCount < 20) {
setNoteCount(n => n + 1)
}
else {
alert('too many notes. remove or combine some of them together!')
}
}
return (
<div>
<Header/>
{[...Array(noteCount)].map((_, i) => <Main onUpdateNoteCount={() =>setNoteCount(n => n - 1)} key={i} />)}
<button
style={{left: '5%'}}
id='addNoteBtn'
onClick={multiplyNoteComponent}
title='Add a note'
>
+
</button>
</div>
);
}
export default App;
Main.js
import React from 'react';
import Note from './Note';
function Main () {
return (
<main>
your notes are:
<Note/>
</main>
)
}
export default Main;
Note.js
import React from 'react';
function Note () {
return (
<div> <button title='delete note' onClick={}>X</delete>
<li>
<input type='text'/>
</li>
</div>
)
}
export default Note
Edit: the reason I think I need the setNoteCount() function to be used in the Note() component, is for the count down when a note is being deleted (every note has its own delete button).
I would recommend this architecture of the your App.
Store the Notes array at the App level.
Add a note using NoteInput which adds a notes to your Notes array.
Map your Notes using the Note component which takes onDelete as a prop from App level.
Your App component should be responsible for storing and delete a note from the state.
In your example, notesCount is meant to a derivative state.
i.e it could be derived simply from the Notes array (notes.length).
So, rather than storing notesCount, I recommend storing notes and deriving count from it.
You could see the working example here :- https://stackblitz.com/edit/react-g19tei
import React from "react";
import "./style.css";
const NOTES_ALLOWED = 10;
export default function App() {
const [notes, setNotes] = React.useState([]);
function addNote(newNote) {
if (notes.length === NOTES_ALLOWED) {
alert(`Only ${NOTES_ALLOWED} notes are allowed to be added`)
} else {
setNotes([...notes, newNote]);
}
}
function handleDelete(deleteNoteIdx) {
const newNotes = [...notes];
// delete the note at the specific index
newNotes.splice(deleteNoteIdx, 1)
setNotes(newNotes);
}
return (
<div>
<div style={{ marginTop: 20, marginBottom: 20 }}>
<p>Your notes are</p>
{notes.map((note, idx) => (
<Note
note={note}
onDelete={() => handleDelete(idx)}
/>
))}
</div>
<NoteInput onAdd={addNote} />
</div>
);
}
function Note({ note, onDelete }) {
return (
<div>
<p>{note}
<button onClick={onDelete}>Delete Note</button>
</p>
</div>
)
}
function NoteInput({ onAdd }) {
const [note, setNote] = React.useState('');
function handleSubmit(e) {
e.preventDefault();
const noteToBeSend = note;
setNote('')
onAdd(noteToBeSend.trim());
}
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={note}
onChange={e => setNote(e.target.value)}
required
/>
<button type="submit">Add Note</button>
</form>
</div>
)
}

Resources