2

I want to render a table in React on a page. Table has contains a lot of rows so I want to apply pagination. Like when someone clicks on page 2 link(/open_alerts/?page=2), table fetches next rows while keeping the same page and just changing the data. But i am facing problem, i can not know in my AlertsTable component the value of page parameter. i saw something useParams hook but this is not allowed in class component. How can I achieve the desired thing?

Home page is at / and it contains link to /open_alerts/ page. App.js:

    <Router>
    <Switch>
      <Route exact path="/">
        <Link to="/open_alerts/">Open Alerts</Link>
        <div className="Charts">
          <AlertsChart id="alerts-chart"/>
          <RegionsChart id="regions-chart"/>
        </div>
      </Route>
      <Route path="/open_alerts/"> 
        <Link to="/">Home page</Link>       
        <AlertsTable />
      </Route>
    </Switch>
    </Router>

How do i know in AlertsTable component the page number so that i may use page number in my API call to server to get the paginated response?

alerts_table.js:

    export class AlertsTable extends React.Component {
    .
    . // code here
    .
    render() {
        return (
          <div>
            <h1>
              Open alerts
            </h1>
            { !this.state.isfetched ? <p>Fetching open alerts</p>: 
            <div>
              <AlertsRenderer alerts={this.state.alerts}/>
              <PaginatedButton pages={this.state.pages_count} />
            </div> }
          </div>
        );
      }
    }

paginated_button.js:

    export function PaginatedButton(props) {
      return (
        <Router>
        {props.pages.map(page_no => (
          <button>
            <Link exact to={"/open_alerts/?page="+(parseInt(page_no)+1)}>{page_no+1}</Link>
          </button>
        ))}
        </Router>
    )}

AlertsRenderer is just a functional component that gets alerts from props and displays using HTML table tags.

  • > "I saw something useParams hook but this is not allowed in class component" Why not change it to a functional component? Class components are pretty much deprecated nowdays. – XCS Mar 28 '21 at 23:03
  • i just know hooks superficially. don't have enough time to go through them in a day – xdgdeveloper Mar 28 '21 at 23:08
  • I highly recommend learning hooks, it makes writing React code a lot cleaner and faster, you will save a lot of time in the long run. That being said, if you want to use the old `withRouter` way see this answer: https://stackoverflow.com/a/58636280/407650 . Basically your question is now "how to get router params in React". – XCS Mar 28 '21 at 23:10
  • @XCS It worked. I used withRouter method. Now i am able to get page number from URL into component. But when I click on it, it just changes URL in URL bar but data page remains same. When i manually press reload button, then a page reloads with new data. How is it happening? – xdgdeveloper Mar 28 '21 at 23:59

1 Answers1

1

useParams wouldn't help you anyway since that is the route's match params, nothing to do with an URL's query string parameters.

You will have to process the query string, which can be accessed from the location route prop.

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere',
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

Use URLSearchParams to process the query string.

const search = this.props.location.search;
const queryParams = Object.fromEntries(new URLSearchParams(search));

const search = "?page=2";
const queryParams = Object.fromEntries(new URLSearchParams(search));

console.log(queryParams);

You can access the route props by a number of ways, but with class-based components they are either directly passed when the component is directly rendered by a Route component on the render or component props, or if you decorate the component with the withRouter Higher Order Component.

In your case it seems that <AlertsTable /> is not directly rendered by a Route component so you should decorate AlertsTable with withRouter and access the location prop that is passed.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • It worked. I used withRouter method. Now i am able to get page number from URL into component. But when I click on it, it just changes URL in URL bar but data page remains same. When i manually press reload button, then a page reloads with new data. How is it happening? – xdgdeveloper Mar 28 '21 at 23:58
  • @xdgdeveloper Remove the extra `Router` component around your links in `PaginatedButton`. You should also remove any other extra `Router` components you might have elsewhere, you only need a single `Router` component in your app. The issue here is multiple routing contexts. The router closest to the links is handling the URL change, but the router handling the routes for the components doesn't see the URL change until you are reloading the page like your are. – Drew Reese Mar 29 '21 at 00:01
  • i have removed that, it's still not working. But can you still explain why only one router works and having multiple makes problems in detecting URL change? Thanks a lot – xdgdeveloper Mar 29 '21 at 00:13
  • @xdgdeveloper The closest routing context in React's virtual DOM will handle any routing logic, so in your code the router around the paginator handles the link and updating the address bar and doesn't propagate anything further up the tree, so any other routing contexts there won't be aware of the link or address bar changing. This is why you only really need a single router. – Drew Reese Mar 29 '21 at 00:30
  • Ok, got it.it still just changes URL in URL bar but doesn't change the data until i manually hot reload button of browser – xdgdeveloper Mar 29 '21 at 07:25
  • @xdgdeveloper This appears to be a separate off-topic issue from this question but my guess is that the `AlertsTable` component may need to implement the `componentDidUpdate` lifecycle method to "react" to the updated `location` prop value. Feel free to ask a new question on stackoverflow and ping me here, or try reproducing this issue into a *running* codesandbox and link here and I can take a look. In either case it sounds like the original issue here with accessing the query params is resolved? – Drew Reese Mar 29 '21 at 07:32
  • yeah, original question was just about params. I have accept your answer. thanks. – xdgdeveloper Mar 29 '21 at 11:55