React Hooks Beginners Finds Difficult to Understand
These are hooks that's very easy to use but some developers finds it difficult to understand (useRef, useReducer, useContex
Table of contents
INTRODUCTION
React hooks are in-built functions that allows you to access state and other React features without using class component. It was introduced in the React 16.8 version. We will only be looking at these React hooks:
- useRef
- useReducer
- useContext
useRef
useRef hook is used to store a mutable values that does not re-render when updated. It can be used to access the DOM element directly.
This is how useRef hook works,
// import useRef from react
import { useRef } from 'react';
const App = ()=> {
//You call the useRef hooks
const anyName = useRef()
// You then assign the property you want to use on it
anyName.current.focus
return (
//Then you use it by calling the current value where you want to use it in
<input type='text' ref={anyName} />
)
This property you assigned is not yet working , you have to make it work by using useEffect hook or any other hook or a button click.
Example :
Here, useRef hook is used together with useEffect hook to change the count whenever the value of change changes as the button is clicked and immediately the page loads .
Note that , useRef returns a mutable ref object whose .current property is initialized to the passed argument (0). The returned object will persist for the full access of the component .
import { useEffect, useRef, useState } from "react";
function App() {
const count = useRef(0);
const [change, setChange ] = useState(true)
useEffect(() => {
count.current = count.current + 1;
console.log(count.current)
}, [change]);
return (
<div className="container">
<p>{count.current}</p>
<button onClick={()=> setChange(!change)}> Click me </button>
</div>
)
}
export default App;
The count started from 2 to display on the screen instead of 1 , this is because useEffects renders after the page loads , you can only see the correct counting using console.log current count inside the useEffect hook to see this
useEffect(() => {
count.current = count.current + 1;
console.log(count.current)
}, [change]);
This is not a very cool example , i just used it for you to understand how easy using useRef can be. Let's look at this cool one here,
import { useRef, useState } from "react";
function App() {
const inputRef = useRef(null);
const [ name, setName ] = useState('')
const onSubmit = (e) => {
//to prevent the page from submitting until the input are available and the button is clicked
e.preventDefault()
//getting the input values
const inputValue = inputRef.current.value;
//assigning it to name
setName(inputValue)
//reset the value to initial
inputRef.current.value = ''
// sets the focus on the input box
inputRef.current.focus()
}
return (
<div className="container">
<p>{name}</p>
<form action="" onSubmit={onSubmit}>
<input type="text" ref={inputRef} required placeholder="Username" />
<button type="submit">Enter</button>
</form>
</div>
)
}
export default App;
Here, useRef is used to store the input values
We used the useRef property .value to store the input value and then set the value of name to be the input value when the submit button is clicked. The useRef property .focus sets the focus on the input box .
Preview
useReducer
This is similar to useState hook, the difference is that it helps to keep track of multiple pieces of state that rely on complex logic.
useReducer takes in two arguments, which is (reducer, initialState)
The reducer is a function (you can name it anything you want like reducer) and it contains your state logics while the initialState is just a variable which is an object.
This is an example of a counter where the decrement button decrease the count and also toggles the background color .
Example:
import React from 'react';
import { useReducer } from 'react';
// reducer function which contains the state logics
const reducer = (state, action) => {
switch(action.type) {
// increases the count only
case "INCREMENT":
return ({count: state.count + 1, changeColor: state.changeColor});
break;
// decreases the count and also changes the background color
case "DECREMENT":
return ({count: state.count - 1, changeColor: !state.changeColor})
break;
default:
return state;
}
}
const App = () => {
const [state, dispatch] = useReducer(reducer,{ count: 1, changeColor: true});
// increment count
const increment = () => {
dispatch({type: "INCREMENT"})
}
//decrement count
const decrement = () => {
dispatch({type: "DECREMENT"})
}
return (
<div style={{backgroundColor: state.changeColor ? "yellow" : "skyblue"}}>
<p>{state.count}</p>
<button className='increment' onClick={increment}>Add</button>
<button className='decrement' onClick={decrement}>Substract</button>
</div>
)
}
export default App
Dispatch is a special function that dispatches an action object. Whenever a state is updated through event handler or fetch request , it is the dispatch function that was called to tell the type of object you shound handle => dispatch(action Object).
useContext
React’s useContext hook makes it easy to pass data throughout your app without manually passing props down the tree.
Instead of passing props from the parentNode down the tree till it reaches the required component, useContext helps you to pass data directly to the component where it is needed.
Here, the same data is passed to firstNode child and secondNode using useContext . Like this image =>
unlike using props , you have to pass data from firstNode before passing it down to FirstNode Child
Example:
- First Create a Context component (optional), then create a CountContext js file.
- Inside the file ,import createContext and create your context by using createContext .
- Export the created context using a function.
- Insert {children} as props (this children represent all the component that will use the value ) .
- Create the state or values you wish to pass .
- Wrap the {children} in the context Provider .
// currencyProvider file where i created my context
import React, { createContext, useContext, useState } from 'react';
//created my context with the variable name => Currencycontext
const CurrencyContext = createContext();
//export your context (to be used by any component)
export function useCurrency() {
return useContext(CurrencyContext)
}
//insert your children as props
export const CurrencyProvider = ({children}) => {
// the state i am passing
const [currencySign, setcurrencySign] = useState({Dollar: '$',Euro: '€',})
return (
//wrap the children in the context provider
<CurrencyContext.Provider value={currencySign}>
{children}
</CurrencyContext.Provider>
)
}
Then inside the App.js file,
- Import the currencyProvider . -Import the Count component .
- Wrap Your Count component with currencyProvider . You must wrap the component you want to use the context with the contextComponent where the context was created.
// App.js file
import Count from './Components/Count';
import {CurrencyProvider} from './Context/CurrencySign';
const App = () => {
return (
<CurrencyProvider>
<Count />
</CurrencyProvider>
)
};
export default App;
In the Count component,
- Import the context function => useCurrency .
- Assign it to a variable using anyName ( I used currency ).
- I used useState to toggle the currency sign
//Count component
//import your useCurrency function
import { useCurrency } from "../Context/CurrencySign";
const Count = () => {
const [dollarSign, setDollarSign] = useState(true);
//assign it to a variable
const currency = useCurrency();
return (
<div>
<div className="amount">
{dollarSign ? currency.Dollar : currency.Euro}
170
</div>
<button onClick={()=>setDollarSign(!dollarSign)}>Change CurrencySign</button>
</div>
);
};
export default Count;
Well! I put my best to make it simple and easy to understand , hope you enjoyed it . Do well to like and share. Thanks , see you in the coming article ✌️.