Reputation: 39
Here is my component code for adding a user.
import React, { Component } from 'react';
import UserDataService from '../service/UserDataService';
import { withRouter} from 'react-router-dom';
class ListUsersComponent extends Component {
constructor(props) {
super(props)
this.state = {
users: [],
message: null
}
this.refreshUsers = this.refreshUsers.bind(this)
this.deleteUserClicked = this.deleteUserClicked.bind(this)
this.addUserClicked = this.addUserClicked.bind(this)
this.createUser = this.createUser.bind(this)
}
componentDidMount() {
this.refreshUsers()
}
refreshUsers() {
UserDataService.retrieveAllUsers()
.then(
response => {
console.log(response)
this.setState({ users: response.data })
}
)
}
deleteUserClicked(id) {
UserDataService.deleteUser(id)
.then(
response => {
this.setState({ message: `Delete of ${id} Successful` })
this.refreshUsers()
}
)
}
addUserClicked() {
this.props.history.push(`/courses/-1`)
}
createUser(user) {
UserDataService.addUser(user)
.then(
response => {
this.setState({ message: `User ${user.firstName} ${user.lastName} Successfully added`})
this.refreshUsers()
}
)
}
render() {
return (
<div className="container">
<h3> All Users </h3>
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<div className="container">
<table className="table">
<thead>
<tr>
<th>Id</th>
<th>FirstName</th>
<th>LastName</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{
this.state.users.map(
user =>
<tr key={user.id} >
<td>{user.id}</td>
<td>{user.firstName}</td>
<td>{user.lastName}</td>
<td>{user.email}</td>
<td>
<img src={user.imagePath}></img>
</td>
<td>
<button className="btn btn-warning" onClick={() => this.deleteUserClicked(user.id)}>Delete</button>
</td>
<td>
<button className="btn btn-success" onClick={() => this.updateUserClicked(user.id)}>Update</button>
</td>
</tr>
)
}
</tbody>
</table>
</div>
<div className="row">
<button className="btn btn-success" onClick={this.addUserClicked}>Add</button>
</div>
</div>
)
}
}
export default ListUsersComponent
with simple button html
<div className="row">
<button className="btn btn-success" onClick={this.addUserClicked}>Add</button>
</div>
But when I click the add button I get
TypeError: Cannot read property 'push' of undefined
ListUsersComponent.addUserClicked
http://localhost:3000/static/js/main.chunk.js:188:24
185 | }
186 |
187 | addUserClicked() {
> 188 | this.props.history.push("/user/-1");
| ^ 189 | }
What am i missing here? Im pretty sure all my version are current. Ive posted all the code for ListUsersComponent as requested. I have to type some more info because I have too much code now. Any other needs to help assess my issue
Here is my controller as requested
private UserRepository repo;
@GetMapping("/users")
public Iterable<User> getAllUsers() {
return repo.findAll();
}
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
Optional<User> user = repo.findById(id);
if (user == null) {
ResponseEntity.notFound().build();
return null;
}
ResponseEntity.noContent().build();
return user.get();
}
Upvotes: 1
Views: 239
Reputation: 5657
withRouter
is a higher order component, and it doesn't work by just importing it.
You actually need to wrap your component in withRouter
for it to have access to this.props.history
:
export default withRouter(ListUsersComponent);
You also need to wrap App
with Router
:
import { Router } from "react-router";
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.getElementById('root')
)
Upvotes: 2
Reputation: 6015
You can get access to the history object’s properties and the closest 's match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
for the props to be available in the component, in addition to importing the function, you must call withRouter(Component)
in your case,
export default withRouter(ListUsersComponent);
Upvotes: 0