Wednesday, February 26, 2020

Using a Custom React Hook for a Central Application Refresh

In this post we will review how to create a custom react hook to handle a refresh of an application.
This post is base on the react application that is presented at the post React Bootstrap with NavBar React Router and Styled Components.
We will extend this application by adding a refresh on the top navigation bar.




We want any page in our application to bet able to refresh by clicking on a refresh button that is at the navigation bar. To do this, we create a custom react hook.

hook.js:

import {useEffect, useState} from 'react'
export function useRefreshEvents(loader, refreshVersion) {
  useEffect(() => {
    loader()
  }, [refreshVersion])


  return null}


Notice that a custom hook must have its name starting with "use" word.
The hooks is based on an increment version. Any click on refresh button, causes the state version to increment, hence forcing rerun of the useEffect entry, which on its turn rerun the load callback.


Next, we update the navigation to keep state of the refreshing version.
The refreshing version is updated whenever the refresh is clicked.


app.js:

import 'bootstrap/dist/css/bootstrap.min.css'
import React, {useState} from 'react'
import {Nav, Navbar} from 'react-bootstrap'
import {BrowserRouter, Link, NavLink, Redirect, Route, Switch} from 'react-router-dom'
import Page1 from './page1'
import Page2 from './page2'
import Page3 from './page3'
function App() {
  const [refreshVersion, setRefreshVersion] = useState(0)
  return (
    <BrowserRouter>
      <Navbar bg="dark" variant="dark" expand="sm">
        <Navbar.Brand as={Link} to="/">React Demo App</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav"/>
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="mr-auto">
            <Nav.Link as={NavLink} to="/page1">Page 1</Nav.Link>
            <Nav.Link as={NavLink} to="/page2">Page 2</Nav.Link>
            <Nav.Link as={NavLink} to="/page3">Page 3</Nav.Link>
          </Nav>
          <Nav pullright="true">
            <div style={{color: 'white'}} onClick={() => setRefreshVersion(refreshVersion+1)}>Refresh</div>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
      <Switch>
        <Route exact path='/page1' component={Page1}/>
        <Route exact path='/page2' component={Page2}/>
        <Route exact path='/page3' render={() =>
          <Page3            refreshVersion={refreshVersion}
            setRefreshVersion={setRefreshVersion}
          />
        }/>
        <Redirect from="/" to="/page1"/>
      </Switch>
    </BrowserRouter>
  )
}

export default App



And lastly, we create the page that fetch information whenever it is activated by the hook.


page3.js:

import React, {useState} from 'react'
import {Text} from './style'
import {useRefreshEvents} from './refresher/hook'
function Page3(props) {
  const [activity, setActivity] = useState('')
  useRefreshEvents(load, props.refreshVersion, props.setRefreshVersion)

  async function load() {
    const resp = await fetch('https://www.boredapi.com/api/activity')
    const json = await resp.json()
    setActivity(json.activity)
  }

  return (
    <Text>{activity}    </Text>
  )
}

export default Page3


Final Words


We have reviewed a method of a central refresh mechanism.

This can be even simpler in case our application includes a redux integration.
In this case, there is no need to send the refresh version from the main app.js down to each page.




No comments:

Post a Comment