5

In my application, I have written a function under a functional component and it doesn't work. It says, function is not defined no-undef. But I have written same kind of code in my previous project. What am I doing wrong here? If I convert this to a class component, this works fine. Is it possible to write a code like this? Or do I have to change it to a class component?

import React from 'react';
import { Link } from 'react-router-dom';

import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import { logoutUser, clearCurrentProfile } from '../../actions'; 

const Navbar = props => {

   const { isAuthenticated, user } = props.auth;

   onLogoutClick = e => {
      e.preventDefault();

      props.clearCurrentProfile();
      props.logoutUser();
   }

   const authLinks = (
      <ul className="navbar-nav ml-auto">
         <li className="nav-item">
            <Link className="nav-link" to="/feed">
               Post Feed
            </Link>
         </li>

         <li className="nav-item">
            <Link className="nav-link" to="/dashboard">
               Dashboard
            </Link>
         </li>

         <li className="nav-item">
            <img 
               className="rounded-circle"
               style={{ width: '25px' }} 
               src={user.avatar} 
               alt={user.name} 
            />
            <button 
               type="button"
               className="link-button nav-link" 
               onClick={() => this.onLogoutClick().bind(this)}>  
                  Logout
            </button>      
         </li>
      </ul>
   );

   const guestLinks = (
      <ul className="navbar-nav ml-auto">
         <li className="nav-item">
            <Link className="nav-link" to="/register">
               Sign Up
            </Link>
         </li>

         <li className="nav-item">
            <Link className="nav-link" to="/login">
               Login
            </Link>
         </li>
      </ul>
   );

   return (
      <nav className="navbar navbar-expand-sm navbar-dark bg-dark mb-4">
         <div className="container">
            <Link className="navbar-brand" to="/">
               DevConnector 
            </Link>

            <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#mobile-nav">
               <span className="navbar-toggler-icon"></span>
            </button>

            <div className="collapse navbar-collapse" id="mobile-nav">
               <ul className="navbar-nav mr-auto">
                  <li className="nav-item">
                     <Link className="nav-link" to="/profiles"> 
                        Developers
                     </Link>
                  </li>
               </ul>

               {isAuthenticated ? authLinks : guestLinks}
            </div> 
         </div>
      </nav>
   );
};

Navbar.propTypes = {
   logoutUser: PropTypes.func.isRequired,
   auth: PropTypes.object.isRequired
}

const mapStateToProps = state => ({
   auth: state.auth
});

const mapDispatchToProps = dispatch => ({
   logoutUser: bindActionCreators(logoutUser, dispatch),
   clearCurrentProfile: bindActionCreators(clearCurrentProfile, dispatch)
});

export default connect(mapStateToProps, mapDispatchToProps)(Navbar);

3 Answers 3

5

Define with const onLogoutClick, and you do not need this keyword when calling it.

bind is also unnecessary when you are already using arrow function for lexical binding.

const Navbar = props => {
  // ...

  const onLogoutClick = e => { // use consts or let
    e.preventDefault()

    props.clearCurrentProfile()
    props.logoutUser()
  }

  const authLinks = (
    // ...
        <button
          type="button"
          className="link-button nav-link"
          onClick={onLogoutClick} // no need 'this' keyword
        >

    ...rest of your stuffs
Sign up to request clarification or add additional context in comments.

Comments

1

You got some syntax error: function declaration onLogoutClick must be started with const or let and the stateless component is just a function, so you don't need this when calling it.

import React from 'react';
import { Link } from 'react-router-dom';

import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import { logoutUser, clearCurrentProfile } from '../../actions'; 

const Navbar = props => {

   const { isAuthenticated, user } = props.auth;

   const onLogoutClick = e => {
      e.preventDefault();

      props.clearCurrentProfile();
      props.logoutUser();
   }

   const authLinks = (
      <ul className="navbar-nav ml-auto">
         <li className="nav-item">
            <Link className="nav-link" to="/feed">
               Post Feed
            </Link>
         </li>

         <li className="nav-item">
            <Link className="nav-link" to="/dashboard">
               Dashboard
            </Link>
         </li>

         <li className="nav-item">
            <img 
               className="rounded-circle"
               style={{ width: '25px' }} 
               src={user.avatar} 
               alt={user.name} 
            />
            <button 
               type="button"
               className="link-button nav-link" 
               onClick={onLogoutClick}>  
                  Logout
            </button>      
         </li>
      </ul>
   );

   const guestLinks = (
      <ul className="navbar-nav ml-auto">
         <li className="nav-item">
            <Link className="nav-link" to="/register">
               Sign Up
            </Link>
         </li>

         <li className="nav-item">
            <Link className="nav-link" to="/login">
               Login
            </Link>
         </li>
      </ul>
   );

   return (
      <nav className="navbar navbar-expand-sm navbar-dark bg-dark mb-4">
         <div className="container">
            <Link className="navbar-brand" to="/">
               DevConnector 
            </Link>

            <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#mobile-nav">
               <span className="navbar-toggler-icon"></span>
            </button>

            <div className="collapse navbar-collapse" id="mobile-nav">
               <ul className="navbar-nav mr-auto">
                  <li className="nav-item">
                     <Link className="nav-link" to="/profiles"> 
                        Developers
                     </Link>
                  </li>
               </ul>

               {isAuthenticated ? authLinks : guestLinks}
            </div> 
         </div>
      </nav>
   );
};

Navbar.propTypes = {
   logoutUser: PropTypes.func.isRequired,
   auth: PropTypes.object.isRequired
}

const mapStateToProps = state => ({
   auth: state.auth
});

const mapDispatchToProps = dispatch => ({
   logoutUser: bindActionCreators(logoutUser, dispatch),
   clearCurrentProfile: bindActionCreators(clearCurrentProfile, dispatch)
});

export default connect(mapStateToProps, mapDispatchToProps)(Navbar);

Comments

0

this is not available when using functional component. It is working when using class component because this is available.

change this

onClick={() => this.onLogoutClick().bind(this)}>

to

onClick={onLogoutClick()}>

1 Comment

change your onClick={onLogoutClick()}> to onClick={onLogoutClick}>. we need to pass function reference

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.