Ammar yasser
Ammar yasser

Reputation: 300

How to make a hook that doesn't run immediately

How can I make a custom hook in react that doesn't run immediately until I run it

For example:

const useHook = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState(undefined);

 return [getData, { isLoading, data }];

};

function App() {
  const [getData, { isLoading, data }] = useHook();

  return <></>
}
const [UsingFC ,{props}] = useHook();

Like apollo graphql client useLazyQuery

Upvotes: 0

Views: 167

Answers (3)

Kareem Adel
Kareem Adel

Reputation: 704

creating a custom hook in React that doesn't run immediately and instead run only when explicitly called you can use the concept of function references

import { useState, useRef } from 'react';

const useHook = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState(undefined);
  const getData = useRef(() => {});

  getData.current = () => {
    setIsLoading(true);
    setTimeout(() => {
      setData(/* Your data here */);
      setIsLoading(false); 

    }, 1000); // Replace this with your actual API call or data-fetching logic
  };

  return [getData, { isLoading, data }];
};

function App() {
  const [getData, { isLoading, data }] = useHook();

  return (
    <>
      <button onClick={getData.current}>Fetch Data</button>
    </>
  );
}

Upvotes: 1

Anton Podolsky
Anton Podolsky

Reputation: 850

If you don't want to execute some piece of code when the hook runs, your hook can return a function that wraps that code and which you can run on demand.

Upvotes: 0

Sergey Sosunov
Sergey Sosunov

Reputation: 4600

Basically nothing really interesting in implementation, you are just returning an array with a trigger method and data object.

const { useCallback, useState } = React;

const useHook = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState(undefined);

  const getData = useCallback(() => {
    setIsLoading(true);

    // do your fetch or whatever
    setTimeout(() => {
      setData("data");
      setIsLoading(false);
    }, 1000);
  }, []);

  return [getData, { isLoading, data }];
};

function App() {
  const [getData, { isLoading, data }] = useHook();

  return (
    <div className="App">
      <p>IsLoading: {isLoading.toString()}</p>
      <p>Data: {data}</p>

      <button type="button" onClick={getData}>
        Get
      </button>
    </div>
  );
}


// v18.x+
ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <App />
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

Upvotes: 2

Related Questions