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

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)
}};```

Related

uploading data to table getting no result

hello iam following mosh hamedani course at some point i got stuck in uploading data in table
this is my table where title and genre is uploading where in stock and rate these are number not string are not uploading here is my table body
class TableBody extends Component {
render() {
const {data,columns} = this.props
console.log({data,columns})
return ( <tbody>
{data.map(item => <tr key={item._id}>
{columns.map(column => <td key={item._id + (column.path || column.key)}>{_.get(item,column.path)}</td>)}
</tr>
)}
</tbody>
);
}
}
data and columns are coming from movietable component here is the code
class MovieTable extends Component {
columns =[
{ path:'title',label:'Title'},
{ path:'genre.name',label:'Genre'},
{ path:'numberInstock',label:'stock'},
{ path:'dailyReantalRate',label:'Rate'},
{ key: 'like' },
{key: 'delete' }
];
render() {
const {movies, onDelete,onSort ,onLike,sortColumn,onAdd,deleted} = this.props;
return (
<table className="table">
<TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort}/>
<TableBody data={movies} columns={this.columns}/>
<tbody>
{movies.map((movie) => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
{" "}
<Like
liked={movie.liked}
onClick={() => onLike(movie)}
/>{" "}
</td>
<td
onClick={() => onDelete(movie._id)}
className="btn btn-danger btn-outline-warning btn-sm active "
>
Remove
</td>
</tr>
))}
</tbody>
<tbody>
{deleted.map((movie) => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
{" "}
<Like />{" "}
</td>
<td
onClick={() => onAdd (movie._id)}
className="btn btn-danger btn-outline-primary btn-sm active "
>
ADD
</td>
</tr>
))}
</tbody>
</table>
);
}
}
movies from props coming from its parent movies component here is movies component code
class Movies extends Component {
state = {
movies:[],
deleted: [],
genres:[],
pageSize: 9,
currentPage:1,
sortColumn:{
path:'title',
order:'asc'
}
};
componentDidMount(){
const genres =[{ _id:"",name:'All Genres'},...getGenres()]
this.setState({
movies:getMovies(),
genres
})
}
handleDelete = (_id) => {
const movie = this.state.movies.find((x) => x._id === _id);
this.setState({ deleted: [...this.state.deleted, movie] });
this.setState({ movies: this.state.movies.filter((x) => x._id !== _id) });
};
handleLike = (m) => {
const movies = [...this.state.movies];
const index = movies.indexOf(m);
movies[index] = { ...movies[index] };
movies[index].liked = !movies[index].liked;
this.setState({ movies });
};
handleReinstate = (_id) => {
const movie = this.state.deleted.find((movie) => movie._id === _id);
this.setState({ movies: [...this.state.movies, movie] });
this.setState({
deleted: this.state.deleted.filter((movie) => movie._id !== _id),
});
};
handleGenreSelect = genre => {
this.setState({selectedGenre:genre, currentPage:1})
}
handleSort= sortColumn =>{
this.setState({sortColumn});
}
render() {
const { pageSize,currentPage,sortColumn,selectedGenre,movies:allMovies,deleted} = this.state;
const filtered = selectedGenre && selectedGenre._id ? allMovies.filter(m=>m.genre._id === selectedGenre._id ): allMovies;
const sorted = _.orderBy(filtered, [sortColumn.path],[sortColumn.order]);
const movies = paginate(sorted,currentPage,pageSize)
return (
<div className="row">
<div className="col-2">
<ListGroup items={this.state.genres} selectedItem={this.state.selectedGenre} onItemSelect={this.handleGenreSelect}/>
</div>
<div className="col">
<div className={this.getbadgesClasses()}> <p>there are {filtered.length} movies in our data base</p> </div>
<MovieTable
movies={movies}
onSort={this.handleSort}
onDelete={this.handleDelete}
onLike={this.handleLike}
deleted={deleted}
onAdd={this.handleReinstate}/>
<Pagination
itemCount={filtered.length}
pageSize={pageSize}
sortColumn={sortColumn}
onPageChange={this.handlePageChange}
currentPage={currentPage}
/>
</div>
</div>
);
}
getbadgesClasses() {
let classes = " badge m-2 badge-";
classes += this.state.movies.length === 0 ? "warning" : "primary";
return classes;
}
handlePageChange = (page) => {
this.setState({currentPage: page})
};
}
this is my console.log
i have give aerong path to Columns array its like spelling mistake in path

No class .db.model.FileDB entity with id 0 exists?

I have a REST API in Spring Boot with JPA and Spring Security ,I manage to upload a file and download it successfully but when I try to delete an existing user object in my database by ID, I get the following error message:
org.springframework.dao.EmptyResultDataAccessException: No class model.FileDB entity with id
undefined exists!
I am new to react / springboot and I cannot find the exact error please HELP.
fileDB MODEL
#Entity
#Table(name = "files")
public class FileDB {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
FileController.java
#DeleteMapping("/files/{id}")
public ResponseEntity<String> deleteFile(#PathVariable String id){
storageService.deleteFile(id);
return new ResponseEntity<>("file deleted", HttpStatus.OK);
}
FileService.java
public void deleteFile(String id) {
fileDBRepository.deleteById(id);
}
******react
export default class UploadFiles extends Component {
constructor(props) {
super(props);
this.selectFiles = this.selectFiles.bind(this);
this.upload = this.upload.bind(this);
this.uploadFiles = this.uploadFiles.bind(this);
this.state = {
selectedFiles: undefined,
progressInfos: [],
message: null,
fileInfos: [],
files:[]
};
}
componentDidMount() {
UploadService.getFiles().then((response) => {
this.setState({
fileInfos: response.data,
});
});
}
deleteFile=(fileId) =>{
axios.delete("http://localhost:8181/files/"+fileId)
.then(response => {
if(response.data !=null){
this.setState({
files:this.state.files.filter(file => file.id !== fileId)
});
}
});
};
render()
{
//code
<Table bordered hover striped variant="dark" >
<thead>
<tr>
<th> List of Files </th>
<th> Actions</th>
</tr>
</thead>
<tbody>
{
fileInfos &&
fileInfos.map((file, id) =>
<tr key = {id}>
<td> <a href={file.url}>{file.name}</a> </td>
<td>
<ButtonGroup>
<Button onClick={this.deleteFile.bind(this,id)}
size="sm" variant="outline-danger">
<FontAwesomeIcon icon={faTrash} />
</Button>
{' '}
<Button size="sm" variant="outline-danger">
<FontAwesomeIcon icon={faEye} />
</Button>
</ButtonGroup>
</td>
</tr>
)
}
</tbody>
</Table>
}
Your Java code APi it's working properly, i thin the problem is in your client side, if the response of UploadService.getFiles() is something like this:
{
....
data:[
{
"id": "afd564",
"name": "hello",
"link": "this the link"
}
]
....
}
export default class UploadFiles extends Component {
constructor(props) {
super(props);
this.selectFiles = this.selectFiles.bind(this);
this.upload = this.upload.bind(this);
this.uploadFiles = this.uploadFiles.bind(this);
this.state = {
selectedFiles: undefined,
progressInfos: [],
message: null,
fileInfos: [],
files:[]
};
}
componentDidMount() {
UploadService.getFiles().then((response) => {
this.setState({
fileInfos: response.data,
});
});
}
deleteFile=(fileId) =>{
axios.delete("http://localhost:8181/files/"+fileId)
.then(response => {
if(response.data !=null){
this.setState({
files:this.state.files.filter(file => file.id !== fileId)
});
}
});
};
render()
{
//code
<Table bordered hover striped variant="dark" >
<thead>
<tr>
<th> List of Files </th>
<th> Actions</th>
</tr>
</thead>
<tbody>
{
fileInfos &&
fileInfos.map((file, id) =>
<tr key = {id}>
<td> <a href={file.url}>{file.name}</a> </td>
<td>
<ButtonGroup>
<Button onClick={this.deleteFile.bind(this,file.id)}
size="sm" variant="outline-danger">
<FontAwesomeIcon icon={faTrash} />
</Button>
{' '}
<Button size="sm" variant="outline-danger">
<FontAwesomeIcon icon={faEye} />
</Button>
</ButtonGroup>
</td>
</tr>
)
}
</tbody>
</Table>
}

add a click event after deleting list

i have created a fuction in which onClick i delete movie but I also want to add a add button by which clicking on add button i get my deleted movie back
here is my code
class Movies extends Component {
state = {
movies: getMovies(),
};
handleDelete=(movi)=>{
const movies = this.state.movies.filter(m=> m._id !== movi._id)
this.setState({movies})
}
render() {
return (
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Rate</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.movies.map((movie) => (
<tr key={movie._id}>
<td >{movie.title}</td>
<td >{movie.genre.name}</td>
<td >{movie.numberInStock}</td>
<td >{movie.dailyRentalRate}</td>
<td onClick={()=>this.handleDelete(movie)} className="btn btn-danger btn-outline-warning btn-sm active ">Remove</td>
</tr>
))}
</tbody>
</table>
);
}
}
You need to somehow keep track of the movies that you are deleting so that you can reinstate them... 3 Components (App - parent, Movie & Deleted)
Here is your App:
export default class App extends Component {
state = { movies: getMovies(), deleted: [] };
handleDelete = id => {
const movie = this.state.movies.find(movie => movie.id === id);
this.setState({ deleted: [...this.state.deleted, movie] });
this.setState({
movies: this.state.movies.filter(movie => movie.id !== id)
});
};
handleReinstate = id => {
const movie = this.state.deleted.find(movie => movie.id === id);
this.setState({ movies: [...this.state.movies, movie] });
this.setState({
deleted: this.state.deleted.filter(movie => movie.id !== id)
});
};
render() {
return (
<div>
<h1>Movies</h1>
{this.state.movies.map(movie => {
return (
<Movie
key={movie.id}
movie={movie}
handleDelete={this.handleDelete}
/>
);
})}
<hr />
<h1>Deleted</h1>
{this.state.deleted.map(movie => {
return (
<Deleted
key={movie.id}
movie={movie}
handleReinstate={this.handleReinstate}
/>
);
})}
</div>
);
}
}
Here is your Movie:
export default function Movie({ movie, handleDelete }) {
return (
<div>
<h4>{movie.title}</h4>
<button onClick={() => handleDelete(movie.id)}>Delete</button>
</div>
);
}
Here is your Deleted / Reinstate:
export default function Deleted({ movie, handleReinstate }) {
return (
<div>
<h4>{movie.title}</h4>
<button onClick={() => handleReinstate(movie.id)}>Reinstate</button>
</div>
)
}
Here is a link to a live demo: https://stackblitz.com/edit/react-umffju?file=src%2FApp.js
For this type of problem, here’s what you could do. Store the deleted movies in state with something like this:
This.state={
currentMovies: [list of movies],
deletedMovies: [list of movies]
}
Have an array that stores Json objects like your movies. Then have a function for storing movies that have been deleted:
const deleteMoviesArray=[]
deleteMovie(movieData){
deleteMoviesArray.push(movieData);
This.setState({
deletedMovies: deletedMoviesArray
})
};
Now you have stored your deleted movies. To retrieve your deleted movies, you might use a drop down box something like this:
<select>
{
This.state.deletedMovies.map(data =>(
<option> {movie.title}</option>
))
}
</select>
And once you select one, do a similar thing to what you did with deleted movies, add a movie back to an array of available movies.
If you need your list of deleted movies to persist past a page refresh, you might consider storing that data in session storage:
window.sessionStorage.setItem(‘deletedMovieArray’, [list of movie objects])
And get them
window.sessionStorage.getItem(‘deletedMovieArray’)

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 pass parameter to a function on onClick event in 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>
)
})

Resources