React

by Abdul Ahmad

HTML

<div id="app"></div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

React

function App() {
	const { valPromise } = useSomeHook();
  const [state, setState] = React.useState();
  
  React.useEffect(() => {
  	valPromise.then(r => {
    	setState(r);
    });
  }, []);
  
  if (!state) return 'not resolved yet';
  return 'resolved: ' + state;
}

function usePromiseValue() {
    const resolveRef = React.useRef();
    const promiseRef = React.useRef(createPromise({ resolve: res }));
    const reset = React.useCallback(() => {
    	promise.current = createPromise({ resolve });
    }, []);
    const promise = promiseRef.current;
    const resolve = resolveRef.current;
    
    React.useEffect(() => {
    	
    }, [promise.current]);

    return {
        promise,
        resolve,
        reset,
    };
}

function createPromise({ resolve } = {}) {
    return new Promise(_resolve => {
        // - useRef is actually called on every render, but the
        //   subsequent result is discarded
        // - however, this can cause the `resolve.current` to be overwritten
        //   which will make the initial promise unresolvable
        // - this condition takes care of ensuring we always resolve the
        //   first promise
        if (!resolve.current) resolve.current = _resolve;
    });
}

function useSomeHook() {
  const [state, setState] = React.useState();
  const { resolve, promise: valPromise, reset } = usePromiseValue({ dependencies: [state] });
  
  React.useEffect(() => {
  	getValTimeout({ setState });
    toggleValue({ setState });
  }, []);
  
  React.useEffect(() => {
  	if (!state) return;
    console.log('*** state', state);
    resolve(state);
    reset();
  }, [state]);
  
  return { valPromise };
}

function getValTimeout({ setState }) {
	setTimeout(() => {
  	setState('the val');
  }, 1000);
}

let count = 0;
function toggleValue({ setState }) {
	setInterval(() => {
  	count += 1;
		setState(count);
  }, 2000);
}


ReactDOM.render(<App />, document.querySelector("#app"))