JSFiddle - React, Tailwind, and code Playground

by Valentin Sarychev

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

JavaScript

function useAsync(fn) {
  const [value, setValue] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    let cancelled = false;
    setValue(null);
    setError(null);
    setLoading(true);
    fn().then(result => { //              TODO: add retries
      if (!cancelled) setValue(result);
    }).catch(error => {
      if (!cancelled) setError(error);
    }).then(() => {
      if (!cancelled) setLoading(false);
    });
    return () => {
      cancelled = true;
    }
  }, [fn]);

  return React.useMemo(() => ({value, loading, error}), [value, loading, error]);
}

const f = () => Promise.resolve(1);

function Component() {
	const result = useAsync(f);
	console.log(result);
  return null;
}

ReactDOM.render(React.createElement(Component), document.querySelector("#root"));