This question already has answers here:
Why is my onClick being called on render? - React.js
(5 answers)
Closed 2 years ago.
In react js, if someone used list object mapping to a list as follow:
const removeUser = (email)=>{
alert(email)
}
const usersList = users.map((user) =>
<li key={user._id}>
{user.Name}
{ isAdmin && <FontAwesomeIcon icon={faTrashAlt} onClick={removeuser(user.Email)}/>}
</li>
);
in here, the function inside onClick event is automatically triggered when mounting the list elements component. it will prompt alerts with email addresses automatically.
In react - onClick should get a function to execute, not execute a function like you did.
Wrap your function with arrow key function like this and it will work:
const removeUser = (email) => {
alert(email)
}
const usersList = users.map((user) =>
<li key={user._id}>
{user.Name}
{isAdmin && <FontAwesomeIcon icon={faTrashAlt} onClick={() => removeuser(user.Email)}/>}
</li>
);
You are passing the invocation of the method, you should pass a definition of a method instead.
const usersList = users.map((user) => (
<li key={user._id}>
{ user.Name }
{ isAdmin && <FontAwesomeIcon icon={faTrashAlt} onClick={() => removeuser(user.Email)} /> }
</li>
));
Related
so i'm looping over an array, and every element has a click event :
{optionsCategory.map((c,i) => (
<div className="content" key={i} onClick={(e) => handleCategoryClick(e,c)}>
{c.name}
</div>
))}
upon clicking if the element has a subCategory i want to assing the subCategory array to the optionsCategory
const handleCategoryClick = async (e: React.MouseEvent<HTMLHeadingElement>, c: Category) => {
if(c.subCategories.length > 0) {
setOptionsService([...c.subCategories])
console.log([optionsCategory])
}
else{
setIsCategory(true);
const data = await onActsByServiceIdAndCategoryId(serviceId,c.id);
setActs([...data])
console.log(acts);
}}
in the console the optionsCategory is updated but not in the Dom
You need to put your optionsCategories inside a useState hook, then react will update the dom, for example: https://jsfiddle.net/7u9cqtxd/
In this case, every two seconds i'll push a new value to optionsCategory and react will update the dom.
const [optionsCategory, setCategory] = useState([30, 20, 10]);
setTimeout(() => setCategory([ ...optionsCategory, 50]), 2000);
return (
<div>
{optionsCategory.map((category) =>
<li key={category}>
{category}
</li>
)}
</div>
);
My bad, after looking at it i used setOptionsService instead of setOptionCategory
Right now i am in Home.js page and i want to render Article.js component/page when user click on particular card (Card.js component). Here is my Home.js code
const Home = () => {
const posts = useSelector((state) => state.posts)
const [currentId, setCurrentId] = useState(null)
const handleClick = () => {
return <Article />
}
return (
<div className="container">
<h4 className="page-heading">LATEST</h4>
<div className="card-container">
{
posts.map(post => <Card key={post._id} post={post} setCurrentId={setCurrentId} onClick={handleClick} />)
}
</div>
</div>
)
}
ONE MORE PROBLEM :
How can I send post variable into onClick method? when i send it method is getting called.
Thank You in Advance :)
It sounds like you want to use the React Router? As I take it you want to load the post as its own page?
I should also point out that any function passed to onClick cannot return anything. The only purpose return can serve in an event function is to exit the function early.
I do agree with #Jackson that you might want to to look into React Router. But you don't need it. You can conditionally render the Article component based on the currentId.
A click handler shouldn't return anything. Instead of returning the <Article /> from the onClick callback, you would use onClick to control the currentId state. You can pass a function that sets the currentId to the post id based on the post variable in your map like this: onClick={() => setCurrentId(post._id)}.
The return for your Home component will either render the list of posts or a current post, depending on whether or not you have a currentId or just null.
const Home = () => {
const posts = useSelector((state) => state.posts);
const [currentId, setCurrentId] = useState(null);
return (
<div className="container">
{currentId === null ? (
// content for list of posts - when currentId is null
<>
<h4 className="page-heading">LATEST</h4>
<div className="card-container">
{posts.map((post) => (
<Card
key={post._id}
post={post}
// arrow function takes no arguments but calls `setCurrentId` with this post's id
onClick={() => setCurrentId(post._id)}
/>
))}
</div>
</>
) : (
// content for a single post - when currentId has a value
<>
<div
// setting currentId to null exits the aritcle view
onClick={() => setCurrentId(null)}
>
Back
</div>
<Article
// could pass the whole post
post={posts.find((post) => post._id === currentId)}
// or could just pass the id and `useSelector` in the Article component to select the post from redux
id={currentId}
// can pass a close callback to the component so it can implement its own Back button
onClickBack={() => setCurrentId(null)}
/>
</>
)}
</div>
);
};
To pass in the click hadler the params you want, one could do something like this:
posts.map(post =>
<Card
key={post._id}
post={post}
onClick={() => handleClick(post)} />
)
This question already has answers here:
How to pass all other props to react class?
(5 answers)
Closed 2 years ago.
So say I have a super basic component like this:
function MyComponent({ setIsOpen })
{
return (
<button onClick={() => setIsOpen(false)}></button>
)
}
What is the proper syntax to pass any additional unknown props onto the component, something like so:
function MyComponent({ setIsOpen })
{
return (
<button onClick={() => setIsOpen(false)} {...props}></button>
)
}
Comment above linked to an example. Here it is in case the link breaks:
function MyComponent(props)
{
const {setIsOpen} = {...props};
return (
<button {...props} onClick={() => setIsOpen(false)}></button>
)
}
Code is in app component (I know that's bad) help would be greatly appreciated. I don't know what I'm doing. Everything works at least except for delete button, trying to remove an item from the list after its been added and can't figure it out. They're asking me to add more details but I don't really know what else to say.
import React, {useState, useEffect} from 'react';
import './App.css';
function App() {
const [memories, setMemories] = useState([]);
const [newItem, setNewItem] = useState('');
const dateAndTime = new Date();
const dateString = dateAndTime.toLocaleDateString();
const [allowSubmit, setAllowSubmit] = useState(false);
const handleSubmit = (evt) => {
evt.preventDefault();
if (allowSubmit === true) {
setMemories([...memories,{
id : memories.length,
value : newItem,
date : dateString
}]);
setNewItem('');
setAllowSubmit(false);
}
}
const clearAllMemories = () => {
setMemories([]);
localStorage.setItem('memories',JSON.stringify(memories));
}
useEffect(() => {
const memoriesData = localStorage.getItem('memories');
if (memoriesData) {
setMemories(JSON.parse(memoriesData));
}
},[]);
useEffect(() => {
localStorage.setItem('memories',JSON.stringify(memories));
});
return (
<div className='App'>
<h2>Favorite moments of the day</h2>
<form onSubmit={handleSubmit}>
<textarea className='text-area'
type='text'
value={newItem}
onChange={e => {
setAllowSubmit(true);
setNewItem(e.target.value)
}}
/>
<input className='input-button'type="submit" value="Add Memory"/>
</form>
<h3 className='memories-title'>Memories</h3>
<div className='memories'>
<ul className='ul'>
{memories.map(memories => (
<li key = {memories.id}>{memories.date}{memories.value}
<button onClick={() => {
setMemories(memories.value.split(memories.value, 1));
}}>delete</button>
</li>
))}
</ul>
</div> <br/>
<button className='clear-button'
onClick={clearAllMemories}
>
Clear All Memories
</button>
</div>
);
}
export default App;
I'm seeing something that could be the problem.
<ul className='ul'>
{memories.map(memories => (
<li key = {memories.id}>{memories.date}{memories.value}
<button onClick={() => {
setMemories(memories.value.split(memories.value, 1));
}}>delete</button>
</li>
))}
</ul>
When using the map function with the memories array, you're assigning the array's name to the array element. And then you access memories.value.split (even though it still doesn't much sense) on the onClick callback of the button, wanting to access the array, but probably accessing the array element.
You should give the array element a different name, like memory or memoryElement, to avoid confusion.
When calling the split function (which from looking to the arguments I think you meant to write splice) you would call it directly in the memories array, not memories.value.
I don't know if I have understood the problem well, but this could be a solution?
<ul className='ul'>
{memories.map(memory => (
<li key = {memory.id}>{memory.date}{memory.value}
<button onClick={() => {
setMemories([...memories.filter(m => memory.id !== m.id)]);
}}>delete</button>
</li>
))}
</ul>
Both of these first two snippets appear in a class component.
Here's the onClick handler:
selectChoice = (id) => {
console.log(id)
}
Here's where I call the functional component that generates both the id I need, and the onClick method.
<ReturnChoices choices={this.state.choices} selectChoice={() => this.selectChoice(id)}/>
Here's the functional component.
const ReturnChoices = ({choices, selectChoice}) => {
return choices.map(( choice , index) => (
<li key={index} id={index} onClick={() => { selectChoice(this.id) }}>
{choice}
</li>
))
}
For some reason, id is coming though as 'undefined'
pass the function itself, no need to wrap in additional function:
<ReturnChoices choices={this.state.choices} selectChoice={this.selectChoice}/>
Pass id given as argument from ReturnChoices to its caller function
<ReturnChoices choices={this.state.choices} selectChoice={(id) => this.selectChoice(id)}/>