How to pass parameter to a function on onClick event in ReactJS - reactjs

class UserList extends Component{
constructor() {
super();
this.state = {
list: [],
};
}
componentDidMount() {
this.getList();
}
getList(){
axios
.get('/getList')
.then(response => {
if(response.data.status == 'success'){
this.setState({
list: response.data.list,
});
console.log(response);
}
})
.catch(error => {
if (error.response) {
console.log(error.response);
}
});
}
{/*I want to call this function with userid when remove button is pressed */}
deleteUser(){
}
render(){
if(!localStorage.getItem('name')){
return( <Redirect to={'/login'} /> )
}
return (
<div id="wrapper">
<table className="table table-hover">
<thead>
<tr>
<th>#No</th>
<th>#Name</th>
<th>#Delete</th>
</tr>
</thead>
<tbody>
{
this.state.list.map(function(item, i){
return <React.Fragment>
<tr key={i}>
<td>{item.id}</td>{/* **This is user id** */}
<td>{item.name}</td>
<td>
<button type="button" onClick="deleteUser(item.id)" className="btn btn-danger btn-sm">Remove</button>
</td>
</tr>
</React.Fragment>
})
}
</tbody>
</table>
</div>
)
}
}
export default UserList;
I am new to ReactJS. I am trying to pass userid to function with onClick event to Remove button. But unable to send userid and it shows error. How can I do it. Can anybody help me with this.
I am trying to pass userid to function with onClick event to Remove button. But unable to send userid and it shows error. How can I do it. Can anybody help me with this.
I am trying to pass userid to function with onClick event to Remove button. But unable to send userid and it shows error. How can I do it. Can anybody help me with this.

Your handler is not bound. You need to declare it like this:
onClick={() => this.deleteUser(item.id)}
So change it to:
{this.state.list.map((item, i) => {
return <React.Fragment>
<tr key={i}>
<td>{item.id}</td>{/* **This is user id** */}
<td>{item.name}</td>
<td>
<button
type="button"
onClick={() => this.deleteUser("asd")}
className="btn btn-danger btn-sm"
>
Remove
</button>
</td>
</tr>
</React.Fragment>
})}
And your handler:
deleteUser = (id) => {
console.log(id)
}

You can call a function in ReactJS with:
<button type="button" onClick={() => deleteUser(item.id)}>...</button>
The function call is an expression and hence you need to use {} instead of double quotes.
Another essential ingredient for this to work is the context in which it is called. Currently it is inside a function, like so:
.map(function(item, i) {
})
The function here owns the usage of this inside it and hence this.deleteUser will not work. To get this to work, you need to convert function to an arrow function which has no this binding.
.map((item, i) => {
return (
<button type="button" onClick={() => deleteUser(item.id)}>...</button>
)
})

Related

Why the function I pass to another component is undefined?

What I'm trying to do is to show a modal(which asks if you want to delete the client, yes or no) when the user deletes a client, and to do that I have passed the function as props to the modal component, when the user clicks yes, the delete function is triggered.
ClientList.js
export default function ListClients() {
const [showModal, setShowModal] = useState();
const [userlist, setUserlist] = useState([]);
function deleteClient() {
const userParams = {
clientName:
clientName,
country: country,
clientid: selectedID,
};
axios
.delete(process.env + "client", {
data: clientParams,
})
.then((response) => {
setClientlist(clientlist.filter((client) => client.id !== clientId));
})
.catch((error) => {
console.log(error);
});
}
return(
<div>
<tbody>
{userlist.length > 0 ? (
userlist.map((userlist) => (
<tr key={userlist.id}>
<td>
<div">
{userlist.id}
</div>
</td>
<td>
<button type="button" onClick= {() =>setShowModal(true) }>
Delete
</button>
</td
</tr>
</tbody>
//the idea is to pass the state for modal to show
<ModalDelete showModal={showModal} setShowModal={setShowModal} onDel={() => deleteClient(clientlist.id)}/>
</div>
);
ModalDelete.js
Modal.js
export default function ModalDelete({ showModal, setShowModal,onDel }) {
console.log(onDel)
return(
<div>
{ showModal ? <Transition.Root show={showModal}>
<div>
<p> Are you sure you want to delete the client?</p>
</div>
<div>
<button type="button" onClick={() => {onDel(); setShowModal(false);}>Yes</button>
<button type="button" onClick={() => {setShowModal(false);}} >
Go Back
</button>
</div>
</Transition.Root> : null }
</div>
);
}
So when I console log the onDel in my console it shows that is undefined. Which means nothing is passed.
Is there a way how to pass the function?
I believe there is no issue from React side but after looking to code seems broken for the delete function, as i can see you are sending a param clientlist.id while calling the onDel, hence your deleteClient function must pass all criteria required so that it should not return undefind. try to fix this code may be your issue will get resolved, one more thing while opening the delete modal you must store this clientListId to a new state so that same can be accessed from the local state, because there is no method defind to store current clicked item from user list

Why onClick can't trigger the delete function?

What I'm trying to do is when the user clicks the delete button to delete the client, I want to show a modal that asks: Are you sure you want to delete it, yes or no.
The modal is on another component, and I thought to pass the delete function as props, but when I call the function in onClick method in the yes button, it won't delete.
ClientList.js
export default function ListClients() {
const [showModal, setShowModal] = useState();
const [userlist, setUserlist] = useState([]);
function deleteClient() {
const userParams = {
clientName:
clientName,
country: country,
clientid: selectedID,
};
axios
.delete(process.env + "client", {
data: clientParams,
})
.then((response) => {
setClientlist(clientlist.filter((client) => client.id !== clientId));
})
.catch((error) => {
console.log(error);
});
}
return(
<div>
<tbody>
{userlist.length > 0 ? (
userlist.map((userlist) => (
<tr key={userlist.id}>
<td>
<div">
{userlist.id}
</div>
</td>
<td>
<button type="button" onClick= () => setShowModal(true)}>
Delete
</button>
</td
</tr>
</tbody>
<ModalDelete showModal={showModal} setShowModal={setShowModal} onDel={() => deleteClient(clientlist.id)}/>
</div>
);
ModalDelete.js
export default function ModalDelete({ showModal, setShowModal, onDel}) {
return(
<div>
{ showModal ? <Transition.Root show={showModal}>
<div>
<p> Are you sure you want to delete the client?</p>
</div>
<div>
<button type="button" onClick={() => onDel()}>Yes</button>
<button type="button" onClick={() => {setShowModal(false);}} >
Go Back
</button>
</div>
</Transition.Root> : null }
</div>
);
}
Not sure why the client is not deleted
ModalDelete.js
onClick={() => onDel()}
shoud be
onClick={onDel}

How to map JSON data as a table in React

I'm trying to display data after fetching it, but that does not work :
import React, { Component } from "react";
import { Table, Button, ButtonToolbar } from "react-bootstrap";
const URL = "http://localhost:51644/api/";
let passedAthleteId = 0;
let passedAthleteSessionId = 0;
class AthleteTrainingSession extends Component {
constructor(props) {
super(props);
this.state = {
athleteTrainingSession: [],
discussions: [],
warmups: [],
workouts: [],
stretchings: [],
};
}
componentDidMount() {
this.fetchAthleteTrainingSession();
}
componentDidUpdate() {
this.fetchAthleteTrainingSession();
}
fetchAthleteTrainingSession = () => {
fetch(URL + `Coaches/4/Athletes/1/AthleteSessions/4`)
.then((response) => response.json())
.then((data) => {
this.setState({
athleteTrainingSession: data,
});
});
};
render() {
const {
athleteTrainingSession,
discussions,
warmups,
workouts,
stretchings,
} = this.state;
passedAthleteId = this.props.match.params.athleteId;
passedAthleteSessionId = this.props.match.params.athleteSessionId;
this.discussions = this.state.athleteTrainingSession.Discussions;
this.warmups = this.state.athleteTrainingSession.Warmups;
this.workouts = this.state.athleteTrainingSession.Workouts;
this.stretchings = this.state.athleteTrainingSession.Stretchings;
console.log(athleteTrainingSession);
console.log(this.warmups);
return (
<React.Fragment>
<div>
<h2 className="mt-2">
Programme d'entraînement :{" "}
{athleteTrainingSession.TrainingProgramName}
</h2>
<h4>
Séance d'entraînement : {athleteTrainingSession.TrainingSessionName}
</h4>
</div>
<div>
<ButtonToolbar>
<Button variant="primary">Ajouter</Button>
<Button variant="secondary">Discussion</Button>
</ButtonToolbar>
<h4>Échauffement</h4>
<Table className="mt-4" striped bordered hover size="sm">
<thead>
<tr className="d-flex">
<th className="col-6">Exercice</th>
<th className="col-6">Options</th>
</tr>
</thead>
<tbody>
{warmups.map((warm) => (
<tr className="d-flex" key={warm}>
<td className="col-6">{warm.ExerciseName}</td>
<td className="col-6">
<ButtonToolbar>
<Button className="mr-2" variant="info">
Modifier
</Button>
<Button className="mr-2" variant="danger">
Supprimer
</Button>
</ButtonToolbar>
</td>
</tr>
))}
</tbody>
</Table>
</div>
</React.Fragment>
);
}
}
export default AthleteTrainingSession;
athleteTrainingSession contains the fetched data, and warmups is a sub-object for athleteTrainingSession.
When I console.log(warmups), I can see that it does contain data, but I cannot display it in the table.
athleteTrainingSession contains the fetched data, and warmups is a sub-object for athleteTrainingSession.
When I console.log(warmups), I can see that it does contain data, but I cannot display it in the table.
I think you have misconception of using state in component.
You're able to console the warmups because in your code you console.log(this.warmups), but you render the map with this.state.warmups
you should setState all of the data that you get from fetch, i.e:
fetchAthleteTrainingSession = () => {
fetch(URL + `Coaches/4/Athletes/1/AthleteSessions/4`)
.then((response) => response.json())
.then((data) => {
this.setState({
athleteTrainingSession: data,
warmups: data.Warmups,
workouts: data.Workouts,
discussions: data.Discussions,
stretchings: data.Stretchings,
});
});
};
by doing this way, now you can access the warmups data from this.state.warmups then render it
render() {
const {
athleteTrainingSession,
discussions,
warmups,
workouts,
stretchings,
} = this.state;
return (
<React.Fragment>
...
{warmups.map((warm) => (
<tr className="d-flex" key={warm}>
<td className="col-6">{warm.ExerciseName}</td>
<td className="col-6">
<ButtonToolbar>
<Button className="mr-2" variant="info">
Modifier
</Button>
<Button className="mr-2" variant="danger">
Supprimer
</Button>
</ButtonToolbar>
</td>
</tr>
))}
...
</React.Fragment>
)
}

how to add pagination and fire row click event in table in react js

I have below child component in react which I am rendering on button click event in parent component. Till here I have no problem. Table is getting rendered on page. I have written row click event findDetails() on table. But problem is that rowClick event in not working on row click. Instead of that it get executed when component is rendering on page. I want to execute on rowClick. Below is my code for table component. Also I need to implement pagination as well in same table which I am not sure how to do it.
class Table extends Component {
constructor(props) {
super(props);
this.state = {
};
}
getHeaader = () => {
var tableHeadings = [
"Customer ID",
"Customer Name",
"Address",
"Contact",
];
return tableHeadings.map((key) => {
return <th key={key}> {key.toUpperCase()}</th>;
});
};
getRowsData = (e) => {
return this.props.Data.map((value, index) => {
const {
"Customer_ID",
"Customer_Name",
"Address",
"Contact",
} = value;
return (
<tr
key={CUSTOMER_ID}
onClick={this.findDetails(value)}
>
<td> {CUSTOMER_ID} </td>
<td> {CUSTOMER_NAME} </td>
<td> {Address} </td>
<td> {Contact} </td>
<td>
<button className="btn btn-info">Find Details</button>
</td>
</tr>
);
});
};
findDetails = (value) => {
console.log("in show button", value.count);
if (value["count"] === 0) {
alert("No details for given customer");
}
};
render() {
return (
<div>
<table
id="display-table"
className="table table-bordered table table-hover table table-responsive pagination"
style={{ tableLayout: "fixed" }}
>
<tbody>
<tr>{this.getHeaader()}</tr>
{this.getRowsData()}
</tbody>
</table>
</div>
);
}
}
export default Table;
`
You invoke your onClick in the wrong way. When passing parameters, you have to wrap your function in an anonymous one:
<tr
key={CUSTOMER_ID}
onClick={() => this.findDetails(value)}
>
I'll explain. When passing onClick, React is waiting for a function name (actually a reference), that then it calls, by adding parentheses. If you add them by yourself as you did (onClick={this.findDetails()} ) you invoke the function right away and you pass the RESULT of the function to the onClick listener.

ReactJS: send object as parameter to function, the fields are undefined

I'm react beginner. strange behavior:
I send an objct as parameter to a function. the function get the object , but the function can access field of this object. the fields are undefined.
I send the object 'movie' to the handleClickDelete. see the console logs: the 'movie' object is correct. but the movie._id is undefined.
the component:
class MainList extends Component {
state = {
count: APIMovieService.getMovies().length,
movies: APIMovieService.getMovies()
};
handleClickDelete = movie => {
console.log("delete movie", movie);
console.log("delete movie Id", movie._id);
const updateList = this.state.movies.filter(
iMove => iMove._id === movie._id
);
// APIMovieService.deleteMovie(movie._id);
console.log("updateList: ", updateList);
this.updateState(updateList);
};
updateState = updateList => {
this.setState({ movies: updateList });
this.setState({ count: updateList.length });
};
render() {
return (
<div>
{this.handleCounter()}
{this.test1()}
<table className="table">
<thead>
<tr>
<th scope="col">title</th>
<th scope="col">genre</th>
<th scope="col">in stock</th>
<th scope="col">rate</th>
<th scope="col">delete</th>
</tr>
</thead>
<tbody>
{this.state.movies.map(movie => (
<tr key={movie._id}>
<td scope="row">{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
<button
className="btn btn-danger"
onClick={() => {
this.handleClickDelete({ movie });
}}
>
delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
handleCounter() {
return this.state.count === 0
? "the list is empty"
: this.state.count + " in the list";
}
export default MainList;
the log:
see picture.enter image description here
You are putting the movie inside an object movie.
For access the properties you need to access another movie property before, like this.
movie.movie.__id
To avois this behavior you need to change this:
onClick={() => {
this.handleClickDelete({ movie });
}}
For this
onClick={() => {
this.handleClickDelete(movie);
}}
You are passing the movie as an object. You need to pass it as a variable like:
<button
className="btn btn-danger"
onClick={() => this.handleClickDelete(movie)}
>
delete
</button>
Now you can access it in your handleClickDelete
const handleClickDelete = movie => {
console.log("delete movie", movie);
console.log("delete movie Id", movie._id);
}
Hope this works for you.
Change :
onClick={() => {
this.handleClickDelete({ movie });
}}
To :
onClick={() => {
this.handleClickDelete(movie)
}};```

Resources