Higer Order Components

1. What is HOC

An HOC is a function in React that takes a component and returns a new component with additional props or functionality. It’s a pattern used to share common functionality between components without altering their structure.

2. Example of HOC

Suppose you want to add a “featured” or “promoted” label to some restaurant cards. You can create an HOC that adds this label based on certain conditions.

function withLabel(WrappedComponent, label) {
  return function (props) {
    return (
      <div>
        <WrappedComponent {...props} />
        {props.isFeatured && <span>{label}</span>}
      </div>
    );
  };
}

// Usage
const RestaurantCard = (props) => <div>{props.name}</div>;
const FeaturedRestaurantCard = withLabel(RestaurantCard, "Featured");

3. Creating an Accordion from Scratch

To create an accordion where only one item is open at a time, you would lift the state up to the parent component and manage which accordion is open.

function Accordion({ items }) {
  const [openIndex, setOpenIndex] = React.useState(null);

  const handleClick = (index) => {
    setOpenIndex(index === openIndex ? null : index);
  };

  return (
    <div>
      {items.map((item, index) => (
        <div key={index}>
          <button onClick={() => handleClick(index)}>{item.title}</button>
          {openIndex === index && <div>{item.content}</div>}
        </div>
      ))}
    </div>
  );
}

Lifting State Up: The openIndex state is managed in the Accordion component and is responsible for determining which accordion item is currently open.

4. What is a Controlled and Uncontrolled Component?

Controlled Component: A component where React controls the element’s value via its state. The form data is handled by the React component and passed down as props.

function ControlledInput() {
  const [value, setValue] = React.useState("");

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return <input type="text" value={value} onChange={handleChange} />;
}

Uncontrolled Component: A component where form data is handled by the DOM rather than React. You use refs to access the form data.

function UncontrolledInput() {
  const inputRef = React.useRef(null);

  const handleSubmit = () => {
    alert("A name was submitted: " + inputRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={inputRef} />
      <button type="submit">Submit</button>
    </form>
  );
}

5. What is Props Drilling?

This refers to the process of passing data from a parent component through multiple levels of child components until it reaches the target component. It can make components harder to manage and maintain as the component hierarchy deepens.

function Grandparent() {
  const [data, setData] = React.useState("some data");
  return <Parent data={data} />;
}

function Parent(props) {
  return <Child data={props.data} />;
}

function Child(props) {
  return <div>{props.data}</div>;
}

6. What is Context & createContext?

Context provides a way to share values between components without having to pass props manually through every level of the tree. It is useful for global data like themes, user information, etc.

The createContext function creates a Context object that holds the current value and provides it to its descendants. You use Context.Provider to supply the value and Context.Consumer or useContext to consume it.

const ThemeContext = React.createContext("light");

function ThemedComponent() {
  const theme = React.useContext(ThemeContext);
  return <div>The current theme is {theme}</div>;
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedComponent />
    </ThemeContext.Provider>
  );
}

Task : Create a 4x4 Checkbox Matrix Where Clicking One Unselects Others