简体   繁体   中英

React: call custom hook from useEffect or run code before component mounts

I'm a bit reluctant to even ask this but here goes...

I have a custom hook useScript based off this implementation but I want to call it from useEffect so that it runs before the component mounts but according to the rules of hooks I know I can't do that.

The issue is that I want to delay rendering my component until the script has loaded but I have no way to set state without causing a 'Too many re-renders' Error.

Here are two options I have tried that do NOT work:

  useEffect(() => {
    // Cannot call another hook from inside useEffect
    useScript('https://cdnjs.cloudflare.com/ajax/libs/typescript/3.9.7/typescript.min.js');
  }, []);

and

  const myComponent = (scripts) => {

    const [loaded, setLoaded] = useState(false);

    scripts.forEach(script => {
      useScript('https://cdnjs.cloudflare.com/ajax/libs/typescript/3.9.7/typescript.min.js');
    });

    // where can I call setLoaded ??

    return (loaded && <div>some content</div>);
  };

This should be simple; What am I forgetting???

One approach is for a hook to return a function that executes some functionality.

So instead of:

function useScript() {
  const [isLoaded, setIsLoaded] = useState(false);

  // load the script...

  return [isLoaded]
}

You can do:

function useLoadScript() {
  const [isLoaded, setIsLoaded] = useState(false);

  const loadScript = () => {
    // load the script...
  }

  return [isLoaded, loadScript]
}

So that the functionality can be consumed within another hook:

function MyComponent(props) {
  const [isLoaded, loadScript] = useLoadScript()
  
  useEffect(() => {
    loadScript()
    // ...
  }, [])

  if (!isLoaded) {
    return <p>Loading...</p>
  }

  return (
    // ...
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM