0

I'm helping another developer by adding pagination to a table view of search results. I am new to ReactJS, but am very familiar with vanilla JavaScript. I borrowed code from a ReactJS course, which works fine at home using only Node as the server. At work, we are using Node, Next and PM2.

I'm calling an event handler from an onClick event. The event handler, see below, calls this.setState, but when clicked, I get the error: TypeError: this is undefined

I have tried an arrow function and a normal function. The normal function throws the "undefined" error and the arrow function throws the compile error: "eventHandler is not defined". I've searched here and done a Google search, and I can't find the solution to this problem. There is no class in this component, just some const

function handlePageChange(page){
  this.setState((page)=>({currentPage: page}));
}
const Pagination = (props)=>{
  const {itemsCount, pageSize}=props;
  const pagesCount = Math.ceil(itemsCount / pageSize);
  if (pagesCount===1) return null;
  let active =1;
  const pages = _.range(1,pagesCount+1);
  return (
    <nav>
      <ul className="pagination">
        {pages.map(page=>(
          <li key={page} active={page===active}>
            <a onClick={()=>handlePageChange(page)}>
              {page}
            </a>
          </li>
         ))}
       </ul>
    </nav>
  )
}

Const Demo = (props)=>{
  return (
//  ... div, container, table, then the pagination:
  <Pagination
    itemsCount={props.data.length}
    pageSize={pageSize}
    currentPage={page}
  />
)}
async function getInitialProps(){}
export default Demo

The pagination displays properly when search results are returned. For example, I get 1 and 2 if there are two pages of results. But when I click on either number, I get TypeError: this is undefined on the this.setState line.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
ann mcg
  • 131
  • 1
  • 1
  • 5
  • 1
    While [Dennis offers the right solution](https://stackoverflow.com/a/57207304/1218980) for this specific case, it's important to be familiar with [how the JavaScript context works](https://stackoverflow.com/q/20279484/1218980) before diving into any framework. – Emile Bergeron Jul 25 '19 at 17:36
  • 1
    Use the `useState` hook in a functional component – charlietfl Jul 25 '19 at 17:45

2 Answers2

2

The state must be a part of a function/class, it will be much easier reading the main concepts then googling all the way up to the solution.

class Pagination extends React.Component {
  state = {
    currentPage: 0
  };

  handlePageChange = page => {
    this.setState({ currentPage: page });
  };

  render() {
    const { itemsCount, pageSize } = this.props;
    const pagesCount = Math.ceil(itemsCount / pageSize);
    if (pagesCount === 1) return null;
    let active = 1;
    const pages = _.range(1, pagesCount + 1);
    return (
      <nav>
        <ul className="pagination">
          {pages.map(page => (
            <li key={page} active={page === active}>
              <a onClick={() => this.handlePageChange(page)}>{page}</a>
            </li>
          ))}
        </ul>
      </nav>
    );
  }
}
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
0

Add useState hook since there is no this.setState in functional component

import React, { useState } from 'react';

const Pagination = (props) => {
  const [currPage, setCurrPage] = useState(/* default*/);
  ...

    {pages.map(page => (
        <li key={page} active={page === currPage}>
          <a onClick={() => setCurrPage(page)}>{page}</a>
        </li>
      ))}
  ...
}
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
charlietfl
  • 170,828
  • 13
  • 121
  • 150