React Hooks Crash Course

React Hooks

  • useEffect is use to handle component side effects. Generally used in fetching data, subscribing to events or updating title. The first argument is an callback function that contains the effect we want to run and callback will be called after the component is rendered.
import { useEffect, useState } from 'react';

function MyComponent({ id }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(`https://my-api.com/data/${id}`)
      .then(response => response.json())
      .then(data => setData(data));
  }, [id]);

  return (
    <div>
      {data ? <p>Data: {data}</p> : <p>Loading...</p>}
    </div>
  );
}
  • useState is a hook that allows you to add state to a functional component in React. State is a way to store and manage data that can change over time. It allows you to keep track of data that your component needs to render, such as a value entered in an input field or a toggle state.
import { useState } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

useState returns an array containing two elements, the first one is the current state, and the second one is a function that allows you to update the state.

  • useMemo is used to memoize a value that's expensive to calculate. It takes a function that returns a value and an array of dependencies as arguments. It will only recalculate the value when one or more of the dependencies have changed. The value is then passed as a prop to a child component, and the child component only re-renders when the value changes.
import { useMemo } from 'react';

function MyComponent({data}) {
  const memoizedData = useMemo(() => expensiveCalculation(data), [data]);

  return (
    <div>
      <p>Data: {memoizedData}</p>
    </div>
  );
}
  • useCallback is used to memoize a callback function. It takes a callback function and an array of dependencies as arguments. It will return a new callback function only when one or more of the dependencies have changed. The callback function is then passed as a prop to a child component, and the child component only re-renders when the callback function changes.
import { useCallback } from 'react';

function MyParentComponent({data}) {
  const handleClick = useCallback(() => {
    console.log(data);
  }, [data]);

  return (
    <div>
      <MyChildComponent onClick={handleClick} />
    </div>
  );
}
  • In summary, useMemo is used to memoize a value and useCallback is used to memoize a function. Both are used to make your component more performant by avoiding unnecessary calculations or re-renders.

  • useReducer is a hook that allows you to manage state in a functional component using the concept of a "reducer" function. It's similar to useState, but it is more powerful and flexible, and is better suited for handling complex state updates. The useReducer hook takes two arguments, the first one is the reducer function, and the second one is the initial state. It returns an array containing the current state and a dispatch function that allows you to update the state by dispatching an action.

import { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function MyComponent() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}
  • memo takes a component as its first argument, and an optional compare function as a second argument. The compare function is used to determine if the component should re-render based on the props. If no compare function is provided, memo will use a shallow comparison of the props to determine if the component should re-render.

  • useRef allows you to create a reference to an element or a value in a functional component. It's a way to store a reference to an element or a value that persists between renders.

import { useRef } from 'react';

function MyComponent() {
  const inputRef = useRef(null);

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus Input</button>
    </div>
  );
}
  • In summary, useState is used to manage state in a component and useRef is used to create a reference to an element or a value in a component.

  • useState is useful when you need to keep track of a value that can change over time, and you want the component to re-render when that value changes. useRef is useful when you need to access or manipulate an element in the DOM, or if you need to keep track of a value that should persist between renders but does not need to cause a re-render.

  • createContext is an API in React that allows you to create a context, which is a way to share data between components. It allows you to pass data down through a component tree without having to pass props down manually at every level. context refers to a way to share data between components without having to pass props down manually at every level of the component tree.

When shouldn't you use the Context API?

Everything that consumes a context re-renders every time that context’s state changes. That means that if you’re consuming your context all over the place in your app, or worse, using one context for your entire app’s state, you’re causing a ton of re-renders all over the place

What is a Fragment?

A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM.

What is a portal?

A portal is a way to render children in a dom node that exists outside the dom hierachy of the parent component and it can live anywhere in the dom tree and you most often in ui components like modal.

What are uncontrolled and controlled components?

A controlled component in React is when the component's state directly controls the value of form elements. Changes to the form elements are managed through React's event handlers. Uncontrolled are input values which are typically controlled by users and react does not control.