• Home
    • How-to guides
    • Snippets
    Cheatsheets:LinuxGitBckgrnd

React hooks

August 21, 2021

post-bg

Content
UseState
UseEffect

In a distant past, maybe a year ago or so, if you had a functional component and, all of a sudden realised, that you needed access to your state components or lifecycle methods, you had to convert them into a class component first. That's no longer the case with hooks. A React hook is a function that makes it possible to work with other React features like state and lifecycle methods. UseState is one of React's built-in hooks, and it does just that, it brings class components state functionality into React function components.

React state in a class

The state is what determines how the component behaves and renders. In a class the state is always an object. This is not the case with hooks. The state can be a string, number, boolean or an object with each piece of state holding a single value.

{
    count: 0,
    name: '',
    loading: false
}

A class component state is user-defined, and always a JS object. If some value isn't used for rendering or data flow, it shoudn't be included

UseState hook

Assuming we have a stateless functional component like this one below rendered in the screen.

import React from 'react'
import ReactDOM from 'react-dom'
  const App = () => (
    <div>
        <p>App</p>
    </div>
  )
}

ReactDOM.render(<App />,
document.getElementById('root'));

Adding useState

Import useState from React, set the state vars and initial value to zero — in a class, this will be the object's property type number value; but here it can just be a primitive data type number value. What you should expect to get back from calling 'useState' is an array with two items or values: the current state value, and a function we can call to update the state.

The example below assumes it is a counter application, and I have set useState initial count value to zero. Probably it's worth pointing out that 'count' as one of the two items returned to the array, it could have only been accessed by passing its index value. But since I have destructured the array already, and set count at position zero, I no longer have to.

import React, { useState } from 'react'
  import ReactDOM from 'react-dom'
  const App = (props) => {
    const [count] = useState(props.count);

    return (
      <div>
        <p>Count is ${count}</p>
      </div>
    )
  }
}

A functional component with React hooks. UseState set, value accessed and rendered in the screen.

Adding button to the component

Building upon the previous component, I now add a button and wire up an onClick event listener that will increase the count value by 1. Then, I access the second item returned by useState; which is also destructured and name it setCount.

The onClick event doesn't have to be a standalone function like the one I have defined for the Plus One button. It can also be set inline, similar to what I did for the Minus One button, instead of passing a function call to the onClick event.

const App = (props) => {
  const [
    count, setCount
    ] = useState(props.count);
  const handlePlus = () => {
    setCount(count + 1);
  }
  return (
    <div>
      <p>Count is ${count}</p>
      <button
        onClick={handlePlus}
      >Plus One</button>

    <button
        onClick={() =>
          setCount(count - 1))
        }
      >
      Minus One
    </button>

    </div>
  )
}

App.defaultProps = {
  count: 0
}

Adding more state

Building upon previous component. We're already tracking count. Now, I'll be adding a 'controlled' input box and to see its value as it changes, and I'll render it right next to count.

We're already tracking count — still a primitive type number. This input box's state is completely independent of count - unlike classes where all the state is managed by a single object.

I've added an onChange event that reacts to input value changes. Unlike classes where the old state is merged with new state, in hooks the new state simply takes the place of the old one. I've also added an onClick event, and this doesn't have to be a standalone function like I've done wiht onChange where I declared a function. You can just set it inline, as shown below with Minus One button.

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const App = (props) => {
  const [
    count, setCount
    ] = useState(props.count);

  const [
    text, setText
  ] = useState('');
  const handlePlus = () => {
    setCount(count + 1);
  }
  return (
    <div>
      <p>{text || 'count'}
        is ${count}
      </p>
      <button
        onClick={handlePlus}
      >Plus One
      </button>
      <button
        onClick={() =>
          setCount(count - 1)
        )}
      >Minus One
      </button>

      <input type="text"
        value={text}
        onChange={(e) =>
          setText(e.target.value)
        }
      />

    </div>
  )
}
ReactDOM.render(<App count={0} />,
document.getElementById('root'));

UseState with an array of objects

Example below, a functional component with 'useState' and the state keeping track of changes is an object's array.

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const NoteApp = () =>  {
  const [notes, setNote] = useState([]);
  const [title,setTitle] = useState('');

  const addNote = (e) => {
    e.preventDefault();
    setNote([
      ...notes,
        {
          title
        }
    ])
    //clear form
    setTitle('');

} //addNote

  const removeNote = (noteObj) => {
    let title = noteObj.title;
      setNotes(notes.filter(itm =>
        itm.title !== title
    ))
  }

  return (
    <div>
      <h1>Notes</h1>

      {
        notes.map(itm => {
          <div ket={itmm.title}>
            <h3>{itm.title}</h3>
            <button
              onClick={(itm) =>
                removeNote(itm)}>Delete
            </button>
          </div>
        })
      }

      <p>Add note</p>
      <form onSubmit={addNote}>
        <input type="text"
          onChange={() =>
            setTitle(e.target.value)}
          />
        <button>Submit</button>
      </form>
    </div>
  )

}

Effect hook

Another built-in hook. React describes it as "componentDidMount, componentDidUpdate, and componentWillUnmount combined".

How-to work with effect

Type useEffect and pass a function to it. As shown below, it runs once when the component first mounts, and every time thereafter the state changes.

//hook
useEffect()

//pass a function to hook
useEffect( + () => {})

//placed inside function body
use(effect() => {
  console.log(
    'running effect'
  );
})

Sync state with effect

UseEffect allow us to easily sync our application's state with other parts of the application. In the example below, I'm tracking multiple pieces of state. The input box value and text in the paragraph above it are being tracked with the text var, therefore they must be rendered simultaneously, and by introducing useEffect, I can make sure they're both updated at the same time.

Similarly, I could with Effect, for example leave out any dependencies that aren't needed or maybe negatively impacting the application's performance by unnecessarily calling state too many times. Something you cannot do with classes. At least not very straight-forward.

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const App = props => {
  const [
    count, setCount
  ] = useState(props.count);
  const [text, setText] = useState('');

  useEffect(() => {
    console.log('use effect ran');
    //header
    document.body
      .getElementsByTagName('header')[0]
        .textContent = text;

  },[text])

  return (
    <div>
      <p>The current {text || 'count'}
        is {count}
      </p>
      <button onClick={() =>
        setCount(count -1)}>
          Minus One
      </button>
      <button onClick={() =>
        setCount(props.count)}>
        Reset
      </button>
      <button onClick={() =>
        setCount(count +1)}>
        Plus One
      </button>

      <input type="text" onChange={() =>
        setText(e.target.value)
        )}
      />
    </div>
  )
}

Example above A functional component with two pieces of state: count and text. To set the initial value of header and keep its state updated, I added text to the effect hook's array. It tells React to run componentDidUpdate with each state update.

Effect hook & empty array

Passing an empty array as second argument to the effect hook mimics componentDidMount lifecycle method behaviour.

mounting phase


to be continued...[]

  • Terms & Conditions
  • kcosa.com © 2025
  • Privacy Policy