Working with React Hooks
1. Using useState Hook
| Property | Description | Example |
|---|---|---|
| useState(initialValue) | Initializes a state variable with the provided initial value | const [count, setCount] = useState(0); |
| setCount(newValue) | Updates the state value to newValue | setCount(count + 1); |
Example: Counter Component
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useState hook returns an array with two elements: the current state value and a function to update it.
2. Using useEffect Hook
| Property | Description | Usage |
|---|---|---|
| useEffect | Hook to perform side effects in functional components | useEffect(() => { /* effect */ }, [dependencies]); |
Example: Basic useEffect usage
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
console.log("Component mounted or re-rendered");
});
return <div>Hello World</div>;
}
Example: useEffect with cleanup
import React, { useEffect } from 'react';
function Timer() {
useEffect(() => {
const interval = setInterval(() => {
console.log("Timer tick");
}, 1000);
return () => clearInterval(interval); // Cleanup function
}, []);
return <div>Timer Component</div>;
}
Example: useEffect with dependencies
import React, { useEffect, useState } from 'react';
function DataFetcher({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(setData);
}, [userId]); // Only re-run if userId changes
return <div>{data ? data.name : "Loading..."}</div>;
}
3. Using useContext Hook
The useContext hook allows you to access data from a React context directly within a functional component, without needing to use a class component or manually pass props down through multiple levels of components.
| Property | Description | Example |
|---|---|---|
| useContext(context) | Accepts a context object (created by React.createContext) and returns the current context value for that context. |
const theme = useContext(ThemeContext); |
Example: Using useContext to access theme
import React, { useContext } from 'react';
const ThemeContext = React.createContext();
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.text }}>
Click me
</button>
);
}
function App() {
return (
<ThemeContext.Provider value={{ background: '#000', text: '#fff' }}>
<ThemedButton />
</ThemeContext.Provider>
);
}
useContext will always return the value from the nearest parent Provider in the component tree. If no matching context is found, it will return the default value provided when creating the context.
4. Using useRef Hook
| Property | Description | Usage |
|---|---|---|
| useRef(initialValue) | Creates a mutable ref object whose .current property is initialized to the passed argument | const ref = useRef(0); |
| ref.current | Access or modify the value stored in the ref object | ref.current = 5; |
Example: Managing focus with useRef
import React, { useRef } from 'react';\n\nfunction FocusInput() {\n const inputRef = useRef(null);\n\n const focusInput = () => {\n inputRef.current.focus();\n };\n\n return ({\n <div>\n <input ref={inputRef} type="text" />\n <button onClick={focusInput}>Focus Input</button>\n </div>\n );\n}
Example: Storing a timer ID
import React, { useRef, useEffect } from 'react';\n\nfunction Timer() {\n const timerRef = useRef(null);\n\n useEffect(() => {\n timerRef.current = setInterval(() => {\n console.log('Timer tick');\n }, 1000);\n\n return () => clearInterval(timerRef.current);\n }, []);\n\n return <div>Timer running...</div>;\n}
5. Using useMemo Hook
| Property | Description | Usage |
|---|---|---|
| useMemo | Optimizes performance by memoizing expensive calculations | const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); |
Example: Memoizing a Computation
import React, { useMemo } from 'react';
function expensiveCalculation(num) {
console.log('Computing...');
return num * 2;
}
function MyComponent({ value }) {
const memoizedResult = useMemo(() => expensiveCalculation(value), [value]);
return <div>Result: {memoizedResult}</div>;
}
useMemo hook prevents unnecessary re-computations when dependencies haven't changed.
useMemo for every calculation — only when performance is actually an issue.
6. Using useCallback Hook
| Property | Description | Usage |
|---|---|---|
| useCallback | Hook to memoize functions | const memoizedCallback = useCallback(() => { |
Example: Basic useCallback Usage
import React, { useCallback } from 'react';\n\nconst MyComponent = () => {\n const handleClick = useCallback(() => {\n console.log('Button clicked');\n }, []);\n\n return <button onClick={handleClick}>Click me</button>;\n};
useCallback hook is useful for optimizing child components that rely on function props.
Key Points
useCallbackreturns a memoized version of the callback.- It only changes if one of its dependencies changes.
- Useful for performance optimization in React components.
7. Creating Custom Hooks
Custom hooks are a powerful way to extract and reuse logic across components in React Native. They follow the same naming convention as built-in hooks (e.g., useMyLogic) and can use other hooks internally.
| Hook Name | Description | Usage |
|---|---|---|
| useMyLogic | Extracts reusable logic into a custom hook | const { data, loading } = useMyLogic(); |
Example: Custom Hook for Fetching Data
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData)
.finally(() => setLoading(false));
}, [url]);
return { data, loading };
}
// Usage in component
const MyComponent = () => {
const { data, loading } = useFetch('https://api.example.com/data');
if (loading) return <Text>Loading...</Text>;
return <Text>{data.title}</Text>;
};
8. Using useLayoutEffect Hook
The useLayoutEffect hook is a variant of useEffect that fires synchronously after all DOM mutations but before the browser paints. It's primarily used for reading layout information or making DOM measurements that need to be synchronous.
| Property | Description | Notes |
|---|---|---|
| useLayoutEffect(callback, deps) | Runs a side effect synchronously after DOM updates | Same signature as useEffect, but with synchronous execution |
Example: Reading DOM Dimensions
import React, { useLayoutEffect, useRef } from 'react';
function MyComponent() {
const ref = useRef(null);
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
useLayoutEffect(() => {
const { width, height } = ref.current.getBoundingClientRect();
setDimensions({ width, height });
}, []);
return <div ref={ref}>Dimensions: {dimensions.width} x {dimensions.height}</div>;
}
useEffect, useLayoutEffect blocks the browser from painting, which can cause performance issues if used improperly. It should only be used when you need to read or measure DOM properties synchronously.
9. Using useImperativeHandle Hook
The useImperativeHandle hook allows a parent component to access the ref of a child component, specifically customizing the instance value that is exposed to the parent.
| Parameter | Description | Notes |
|---|---|---|
| ref | The ref object passed to the child component. | Must be a forwardRefed component. |
| getSnapshot | A function that returns the value to be exposed to the parent. | Called during rendering and must be pure. |
Example: Custom ref with useImperativeHandle
import React, { forwardRef, useImperativeHandle } from 'react';\n\nconst CustomInput = forwardRef((props, ref) => {\n useImperativeHandle(ref, () => ({\n focus: () => {\n console.log('Input focused');\n },\n getValue: () => 'Custom Value'\n }));\n\n return <input type="text" />;\n});\n\nexport default CustomInput;
Example: Using ref in parent component
import React, { useRef } from 'react';\nimport CustomInput from './CustomInput';\n\nfunction ParentComponent() {\n const inputRef = useRef();\n\n const handleFocus = () => {\n inputRef.current.focus();\n };\n\n return (\n <>\n <CustomInput ref={inputRef} />\n <button onClick={handleFocus}>Focus Input</button>\n </>\n );\n}
useImperativeHandle should be used sparingly and only when necessary to maintain a clean component architecture.
10. Understanding Hook Rules and Best Practices
| Rule | Description | Example |
|---|---|---|
| Top Level | Hooks must be called at the top level of a component or custom hook. | |
| Conditional Calls | Do not call hooks inside conditions or loops. | |
| Custom Hooks | Custom hooks must start with "use" and can call other hooks. | |