lifecycle HOCs with Recompose

timeouts

by jonahe

HTML

<script src="https://unpkg.com/[email protected]/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script>
<script src="https://unpkg.com/[email protected]/build/Recompose.js"></script>
<div id="root"></div>

Babel + JSX

const { compose, withStateHandlers, branch, lifecycle } = Recompose;

const withNamedToggler = (propertyNameBase, initialValue) => withStateHandlers(
	{ [`${propertyNameBase}IsToggled`] : initialValue },
  {
  	[`${propertyNameBase}Toggler`] : props => (e) => {
    		return { [`${propertyNameBase}IsToggled`]: !props[`${propertyNameBase}IsToggled`] };
    }
  }
);

/*
	EXECUTES A FUNCTION AFTER A DELAY. Handles clearing timeout on unmount (needs testing)
	
  propsToFunctionToRun : a function like props => props.theFunctionToRun 
  delayInMs : delay in milliseconds
  name: name to be used for generating keys/names for values and functions
  
  For a name like "testTimeout", Will produce
  	testTimeout : A number referencing the timeout
    testTimeoutClearer: A function to clear the timeout
    testTimoutHasCleared: a bool indicating whether the timeout has been cleared
*/
const withTimeout = (propsToFunctionToRun, delayInMs, name = `timeout_${(Math.random() * 1000).toFixed(0)}`, autoStart = true) => {
	const timeoutKey = `${name}`;
 // const timeoutHasStartedKey = `${name}HasStarted`;
  const timeoutStarterKey = `${timeoutKey}Starter`;
  const timeoutClearerKey = `${name}Clearer`;
  const timeoutIsClearedKey = `${name}IsCleared`;
  const timeoutHasExecutedKey = `${name}HasExecuted`;
  return compose(
  	// handle 
    lifecycle({
    	state: { [timeoutKey]: null,  [timeoutHasExecutedKey] : false },
      
      executeFunction() {
      	const functionToRun = propsToFunctionToRun(this.props);
        functionToRun();
        this.setState({ [timeoutHasExecutedKey] : true });
      },
    	componentDidMount() {
      	if(!autoStart) return;
        
        const timeoutRef = setTimeout(this.executeFunction.bind(this), delayInMs);
        this.setState({[timeoutKey] : timeoutRef});
      },
      componentWillUnmount() {
      	console.log('unmount. clearing ref', this.state[timeoutKey])
        const { [timeoutHasExecutedKey] : hasExecuted } = this.state;
     ...