An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
useCallback, useMemo, useRef, and useReducer hook
In this article, Im going to discuss the use of useCallback, useMemo, useRef, and useReducer hook.
useCallback hook: It memorizes a callback function. So new instances of that function are not created. And it will only forget it when the dependency value is changed.
import React, { useCallback, useState } from "react";import "./App.css";import Title from "./components/Title/Title";function App() { const [increase1, setIncrease1] = useState(0); const [increase5, setIncrease5] = useState(0); const handleIncrease1 = useCallback(() => { console.log("inside 1"); setIncrease1(increase1 + 1); }, [increase1]); const handleIncrease5 = useCallback(() => { console.log("inside 5"); setIncrease5(increase5 + 5); }, [increase5]); return ( <div className="App"> <Title /> {/* increase value by 1 */} <h4>Increase value by 1</h4> <p>{increase1}</p> <button onClick={handleIncrease1}> Increase by 1</button> {/* increase value by 5 */} <h4>Increase value by 5</h4> <p>{increase5}</p> <button onClick={handleIncrease5}> Increase by 5</button> </div> );}export default App;
UseMemo hooks: Its a little different from useCallback hook. useCallback memorizes the whole function but it memorizes only the return value of a function. And it forgets that when the dependency value is changed.
import React, { useCallback, useMemo, useState } from "react";import "./App.css";import Title from "./components/Title/Title";function App() { const [increase1, setIncrease1] = useState(0); const [increase5, setIncrease5] = useState(0); const handleIncrease1 = useCallback(() => { console.log("inside 1"); setIncrease1(increase1 + 1); }, [increase1]); const handleIncrease5 = useCallback(() => { console.log("inside 5"); setIncrease5(increase5 + 5); }, [increase5]); const isEvenOrOdd = useMemo(() => { let i = 0; while (i < 1000000000) i++; return increase1 % 2 === 0; }, [increase1]); return ( <div className="App"> <Title /> {/* increase value by 1 */} <h4>Increase value by 1</h4> <p>{increase1}</p> <p>{isEvenOrOdd ? "Even" : "Odd"}</p> <button onClick={handleIncrease1}> Increase by 1</button> {/* increase value by 5 */} <h4>Increase value by 5</h4> <p>{increase5}</p> <button onClick={handleIncrease5}> Increase by 5</button> </div> );}export default App;
useRef: If we want to get a element or its value then we use document.getElementById or document.getElementsByClassName etc. You can use them on react but it is not a good practice. To solve this react give us useRef hook. You just have to say which node element you want to reference. Then it will return the referenced node in the referenced variable.current
import React, { useEffect, useRef } from "react";const Form = () => { const inputRef = useRef(); useEffect(() => { console.log(inputRef.current.value); }, []); return ( <div> <input ref={inputRef} /> </div> );};export default Form;
If you have to use ref to a child component then you have to use forward ref to pass ref from parent to child component
Parent component where the ref is located
import React, { useEffect, useRef } from "react";import "./App.css";import Input from "./components/Input";function App() { const inputRef = useRef(); useEffect(() => { inputRef.current.focus(); }); return ( <div className="App"> <Input placeholder="Enter your name" ref={inputRef} type="text" /> </div> );}export default App;
Child component where I want to use the ref
import React from "react";const Input = ({ type, placeholder }, ref) => { return <input ref={ref} type={type} placeholder={placeholder} />;};const forwardedInput = React.forwardRef(Input);export default forwardedInput;
Heres a little trick of using useRef. When you want to use a function which is scoped inside the useEffect hook.
import React, { useEffect, useRef, useState } from "react";const Clock = () => { const [date, setDate] = useState(new Date()); const intervalRef = useRef(); const tick = () => { setDate(new Date()); }; useEffect(() => { intervalRef.current = setInterval(tick, 1000); // do the cleanup stop the timer return () => { clearInterval(intervalRef.current); }; }, []); return ( <div> <p>Time: {date.toLocaleTimeString()}</p> <p> <button onClick={() => clearInterval(intervalRef.current)}>Stop</button> </p> </div> );};export default Clock;
useReducer: useReducer is like the Array.prototype.reduce method in vanilla JS. The difference is that reduce method takes a reducer function and initialValue but useReducer takes the reducer function and initialState as the second parameter. Reduce method returns a single value but useReducer returns a tuple [newState, dispatch]
import React, { useReducer } from "react";import "./App.css";const initialState = 0;const reducer = (state, action) => { switch (action) { case "increment": return state + 1; case "decrement": return state - 1; default: return state; }};function App() { const [count, dispatch] = useReducer(reducer, initialState); return ( <div className="App"> <p>{count}</p> <button onClick={() => dispatch("increment")}>Increase</button> <button onClick={() => dispatch("decrement")}>Decrease</button> </div> );}export default App;
You can use useReducer in a complex situation where you have different as for example counters and they have a different functions to update their value.
import React, { useReducer } from "react";const initialState = { counter: 0, counter2: 0,};const reducer = (state, action) => { /* you have to merge object immutably to do that use the spread operator */ switch (action.type) { case "increment": return { ...state, counter: state.counter + action.value }; case "decrement": return { ...state, counter: state.counter - action.value }; case "increment2": return { ...state, counter2: state.counter2 + action.value }; case "decrement2": return { ...state, counter2: state.counter2 - action.value }; default: return state; }};/* you have to merge state immutably */function Counter() { const [count, dispatch] = useReducer(reducer, initialState); return ( <React.Fragment> {/* counter 1 */} <div> <p>Counter1: {count.counter}</p> <button onClick={() => dispatch({ type: "increment", value: 1, }) } > Increment by 1 </button> <button onClick={() => dispatch({ type: "decrement", value: 1, }) } > Decrement by 1 </button> </div> {/* counter 2 */} <div> <p>Counter2: {count.counter2}</p> <button onClick={() => dispatch({ type: "increment2", value: 1, }) } > Increment2 by 1 </button> <button onClick={() => dispatch({ type: "decrement2", value: 1, }) } > Decrement2 by 1 </button> </div> </React.Fragment> );}export default Counter;
Original Link: https://dev.to/zihad550/usecallback-usememo-useref-and-usereducer-hook-dl
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To