'TypeError: this.props.navigate is not a function
I am new to React.js and I am getting following error "TypeError: this.props.navigate is not a function" while calling this.props.navigate(/todos/${id}) in updateTodoClicked(id) function under ToDoList Component
The same function working working fine in LoginComponent.
Error Log Screenshot:
ToDoList Component:
import React, { Component } from 'react'
import TodoDataService from '../../api/todo/TodoDataService.js'
import AuthenticationService from './AuthenticationService.js'
import moment from 'moment'
class ToDoList extends Component {
constructor(props) {
console.log('constructor')
super(props)
this.state = {
todos: [],
message: null
}
this.deleteTodoClicked = this.deleteTodoClicked.bind(this)
this.updateTodoClicked = this.updateTodoClicked.bind(this)
this.addTodoClicked = this.addTodoClicked.bind(this)
this.refreshTodos = this.refreshTodos.bind(this)
}
componentWillUnmount() {
console.log('componentWillUnmount')
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate')
console.log(nextProps)
console.log(nextState)
return true
}
componentDidMount() {
console.log('componentDidMount')
this.refreshTodos();
console.log(this.state)
}
refreshTodos() {
let username = AuthenticationService.getLoggedInUser()
TodoDataService.retriveAllTodos(username)
.then(
response => {
//console.log(response);
this.setState({ todos: response.data })
}
)
}
deleteTodoClicked(id) {
let username = AuthenticationService.getLoggedInUser()
//console.log(id + " " + username);
TodoDataService.deleteTodo(username, id)
.then(
response => {
this.setState({ message: `Delete of todo ${id} Successful` })
this.refreshTodos()
}
)
}
addTodoClicked() {
this.props.navigate(`/todos/-1`)
//this.props.history.push(`/todos/-1`)
}
updateTodoClicked(id) {
console.log('update ' + id)
this.props.navigate(`/todos/${id}`)
}
render() {
console.log('render')
return (
<div>
<h1>List Todos</h1>
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<div className="container">
<table className="table">
<thead>
<tr>
<th>Description</th>
<th>Target Date</th>
<th>IsCompleted?</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
this.state.todos.map(
todo =>
<tr key={todo.id}>
<td>{todo.description}</td>
<td>{moment(todo.targetDate).format('YYYY-MM-DD')}</td>
<td>{todo.done.toString()}</td>
<td><button className="btn btn-success" onClick={() => this.updateTodoClicked(todo.id)}>Update</button></td>
<td><button className="btn btn-warning" onClick={() => this.deleteTodoClicked(todo.id)}>Delete</button></td>
</tr>
)
}
</tbody>
</table>
<div className="row">
<button className="btn btn-success" onClick={this.addTodoClicked}>Add</button>
</div>
</div>
</div>
)
}
}
export default ToDoList
TodoComponent:
import React, {Component} from "react";
import moment from 'moment';
import {Formik, Form, Field} from 'formik';
class TodoComponent extends Component {
constructor(props) {
super(props)
this.state = {
id : this.props.params.id,
description : 'Learn Forms',
targetDate : moment(new Date()).format('YYYY-MM-DD')
}
}
render() {
return <div>
<h1>Todo</h1>
<div className="container">
<Formik>
{
(porps) => (
<Form>
<fieldset className="form-group">
<label>Description</label>
<Field className="from-control" type="text" name="description"></Field>
</fieldset>
<fieldset className="form-group">
<label>Target Date</label>
<Field className="from-control" type="date" name="targetDate"></Field>
</fieldset>
</Form>
)
}
</Formik>
</div>
</div>
}
}
export default TodoComponent
TodoApp:
enter code here
import React, {Component} from "react";
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom'
import withNavigation from './WithNavigation.jsx'
import withParams from "./WithParams.jsx";
import AuthenticationRoute from "./AuthenticatedRoute.jsx"
import LoginComponent from "./LoginComponent.jsx"
import ToDoList from "./ListTodos.jsx"
import HeadderComponent from "./HeaderComponent.jsx"
import FooterComponent from "./FooterComponent.jsx"
import ErrorComponent from "./ErrorComponent.jsx"
import LogoutComponent from "./LogoutComponent.jsx"
import WelcomeComponent from "./WelcomeComponent.jsx"
import TodoComponent from "./TodoComponent.jsx"
class ToDoApp extends Component {
render() {
const LoginComponentWithNavigation = withNavigation(LoginComponent);
const WelcomeComponentWithParams = withParams(WelcomeComponent);
const HeaderComponentWithNavigation = withNavigation(HeadderComponent);
const TodoComponentWithParamsAndNavigation = withParams(withNavigation(TodoComponent));
return(
<div className="TodoApp">
<Router>
<HeaderComponentWithNavigation></HeaderComponentWithNavigation>
<Routes>
<Route path="/" element={<LoginComponentWithNavigation />}/>
<Route path="/login" element={<LoginComponentWithNavigation />} />
<Route path="/welcome/:name" element={<AuthenticationRoute><WelcomeComponentWithParams/></AuthenticationRoute>} />
<Route path="/todos/:id" element={<AuthenticationRoute><TodoComponentWithParamsAndNavigation /></AuthenticationRoute>} />
<Route path="/todos" element={<AuthenticationRoute><ToDoList /></AuthenticationRoute>}/>
<Route path="/logout" element={<AuthenticationRoute><LogoutComponent /></AuthenticationRoute>}/>
<Route path="*" element={<ErrorComponent />} />
</Routes>
<FooterComponent></FooterComponent>
</Router>
{/*<LoginComponent/>
<WelcomeComponent/>*/}
</div>
)
}
}
export default ToDoApp;
WithNavigation:
import React from "react";
import { useNavigate } from "react-router-dom";
function withNavigation(Component) {
return props => <Component {...props} navigate={useNavigate()} />;
}
export default withNavigation
WithParams: import React from "react"; import { useParams } from "react-router-dom";
function withParams(Component) {
return props => <Component {...props} params={useParams()} />;
}
export default withParams
I am NOT getting any error while calling this.props.navigate(/welcome/${this.state.username}) function in LoginComponent Component
Login Component
import React, {Component} from "react";
import AuthenticationService from "./AuthenticationService.js"
class LoginComponent extends Component {
constructor(props) {
super(props)
this.state = {
username: 'in28Minutes',
password: '',
hasLoginFailed: false,
showSuccessMessage: false
}
this.handleChange = this.handleChange.bind(this)
this.loginClicked = this.loginClicked.bind(this)
}
handleChange(event) {
this.setState({[event.target.name]:event.target.value})
}
loginClicked() {
if(this.state.username==='in28Minutes' && this.state.password==='dummy') {
AuthenticationService.registerSuccessfullLogin(this.state.username, this.state.password)
this.props.navigate(`/welcome/${this.state.username}`)
this.setState({hasLoginFailed:false})
this.setState({showSuccessMessage:true})
}
else{
console.log("Login Failed")
this.setState({showSuccessMessage:false})
this.setState({hasLoginFailed:true})
}
}
render() {
return(
<div>
<h1>Login</h1>
<div className="container">
{/*<ShowInvalidCredentials hasLoginFailed={this.state.hasLoginFailed}/>*/}
{<ShowSuccessMessage showSuccessMessage={this.state.showSuccessMessage}/>}
{this.state.hasLoginFailed && <div className="alert alert-warning">Invalid Credentails</div>}
{/*{this.state.showSuccessMessage && <div>Login Successful</div>}*/}
User Name: <input type="text" name="username" value={this.state.username} onChange={this.handleChange}></input>
<div className="container">
Password: <input type="password" name="password" value={this.state.password} onChange={this.handleChange}></input>
</div>
<button className="btn btn-success" onClick={this.loginClicked}>Login</button>
</div>
</div>
)
}
}
function ShowSuccessMessage(props) {
if(props.showSuccessMessage) {
return <div>Login Success</div>
} else {
return null
}
}
export default LoginComponent
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

