DEV Community

ZeeshanAli-0704
ZeeshanAli-0704

Posted on

React FC Context & useReducer

import React, { createContext, useState } from "react";
import { useContext } from "react";

const CustomThemeContext = createContext();

export const CustomThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState();

  const toggleTheme = () => {
    setTheme(theme == "light" ? "dark" : "light");
  };
  return (
    <>
      <CustomThemeContext.Provider value={{ theme, toggleTheme }}>
        {children}
      </CustomThemeContext.Provider>
    </>
  );
};

export const useTheme = () => useContext(CustomThemeContext);

Enter fullscreen mode Exit fullscreen mode
import { useReducer } from "react";

let initialState = {
  count: 0,
  namme: "ZES",
};

const reducerfn = (state, action) => {
  console.log(state, action);
  switch (action.type) {
    case "ADD":
      return { count: state.count + action.by };
    case "SUB":
      return { count: state.count - action.by };
  }
  return state;
};

const PracticeReducer = () => {
  const [state, dispatch] = useReducer(reducerfn, initialState);

  const handleIncrement = () => {
    dispatch({ type: "ADD", by: 1, x: "x" });
  };

  const handleDecrement = () => {
    dispatch({ type: "SUB", by: 1 });
  };

  return (
    <>
      Display Counter : {state.count} -- {state.namme}
      <button onClick={handleIncrement}>INC</button>
      <button onClick={handleDecrement}>DEC</button>
    </>
  );
};
export default PracticeReducer;

Enter fullscreen mode Exit fullscreen mode

IntersectionObserver

import React, { useState, useEffect, useRef } from "react";

export default function IntersectionObs() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(1);
  const [showDropdown, setShowDropdown] = useState(false);

  const lastItemRef = useRef(null);

  // Fetch posts from JSON Placeholder
  const fetchItems = async () => {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/posts?_limit=10&_page=${page}`
    );
    const data = await response.json();
    setItems((prev) => [...prev, ...data]); // append
  };

  useEffect(() => {
    fetchItems();
  }, [page]);

  useEffect(() => {
    if (!showDropdown || !lastItemRef.current) return;

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) {
          console.log("Reached bottom → loading next page");
          setPage((prev) => prev + 1);
        }
      },
      {
        root: document.getElementById("dropdownContainer"),
        threshold: 1.0,
      }
    );

    observer.observe(lastItemRef.current);

    return () => {
      if (lastItemRef.current) observer.unobserve(lastItemRef.current);
    };
  }, [items, showDropdown]);

  return (
    <div style={{ width: "260px", position: "relative" }}>
      {/* Select-like trigger */}
      <div
        onClick={() => setShowDropdown((prev) => !prev)}
        style={{
          padding: "10px",
          border: "1px solid #ccc",
          cursor: "pointer",
          background: "#fff",
        }}
      >
        Select Post
      </div>

      {/* Dropdown */}
      {showDropdown && (
        <div
          id="dropdownContainer"
          style={{
            maxHeight: "200px",
            overflowY: "auto",
            border: "1px solid #ccc",
            marginTop: "5px",
            background: "#fff",
            position: "absolute",
            width: "100%",
            zIndex: 100,
          }}
        >
          {items.map((item, index) => {
            const isLast = index === items.length - 1;
            return (
              <div
                key={item.id}
                ref={isLast ? lastItemRef : null}
                style={{
                  padding: "10px",
                  borderBottom: "1px solid #eee",
                  cursor: "pointer",
                }}
              >
                {item.title}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)