Modularity

Let's Create Our Own Hook

const [menu, setMenu] = useState(null);
const { id } = useParams();

useEffect(() => {
  const fetchData = async () => {
    try {
      const response = await axios.get(`${REST_MENU_URL}${id}`);
      setMenu(response.data);
    } catch (error) {
      console.error("Error fetching menu data:", error);
    }
  };

  fetchData();
}, [id]);
 const menu = useRestaurantMenu(id);
import { useState, useEffect } from "react";
const useRestaurantMenu = (id) => {
  const [menu, setMenu] = useState(null);
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get(`${REST_MENU_URL}${id}`);
        setMenu(response.data);
      } catch (error) {
        console.error("Error fetching menu data:", error);
      }
    };
    fetchData();
  }, []);
  return menu;
};

Q: Why don't we just use a regular function instead of hooks?

const offline = true;
if (offline) {
  return <h1>Offline</h1>;
}
const offline = useOnline();
import { useState, useEffect } from "react";

const useOnline = () => {
  const [isOnline, setIsOnline] = useState(navigator.onLine);
  const handleOnline = () => {
    console.log("IsOnline is here");
    setIsOnline(true);
  };
  const handleOffline = () => {
    console.log("IsOffline is here");
    setIsOnline(false);
  };
  useEffect(() => {
    window.addEventListener("online", handleOnline);
    window.addEventListener("offline", handleOffline);
  }, []);
  return isOnline;
};
export default useOnline;
return () => {
  console.log("Cleaning the eventListener");
  window.removeEventListener("online", handleOnline);
  window.removeEventListener("offline", handleOffline);
};

Let's Optimize Our App

const Instamart = lazy(() => import("./path/of/component"));
<Suspense fallback={<Shimmer />}>
  <Instamart />
</Suspense>

Good Practices for Lazy Loading

  1. Use React.lazy and Suspense Wisely

    • Tip: Only lazy-load components that are not immediately necessary for the initial render. This helps in reducing the initial load time and improves user experience.
    • Example:
      import React, { Suspense, lazy } from 'react';
      
      const LazyComponent = lazy(() => import('./LazyComponent'));
      
      function App() {
        return (
          <div>
            <Suspense fallback={<div>Loading...</div>}>
              <LazyComponent />
            </Suspense>
          </div>
        );
      }
      
  2. Split Code Strategically

    • Tip: Identify and split large components or routes that can be loaded on-demand. This prevents large bundles and speeds up initial page load.
    • Example:
      import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
      import React, { Suspense, lazy } from 'react';
      
      const Home = lazy(() => import('./Home'));
      const About = lazy(() => import('./About'));
      
      function App() {
        return (
          <Router>
            <Suspense fallback={<div>Loading...</div>}>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route path="/about" component={About} />
              </Switch>
            </Suspense>
          </Router>
        );
      }
      
  3. Optimize Fallback UI

    • Tip: Provide engaging fallback UI during loading to keep users informed and entertained. Consider using spinners, skeleton screens, or other dynamic placeholders.
    • Example:
      <Suspense fallback={<div className="spinner">Loading...</div>}>
        <LazyComponent />
      </Suspense>