Skip to content

Instantly share code, notes, and snippets.

@MacKentoch
Last active March 23, 2019 13:34
Show Gist options
  • Save MacKentoch/e6238505348cdd662b5d6f3246b5694b to your computer and use it in GitHub Desktop.
Save MacKentoch/e6238505348cdd662b5d6f3246b5694b to your computer and use it in GitHub Desktop.

React hook - class lifecycle equivalences

State

//Class
class CounterButton extends Component {
  state = {
    count: 0
  };

  render() {
    const { count } = this.props;

    return <button onClick={this.setCount}>{count}</button>;
  }

  setCount = () => {
    const { count } = this.props;
    this.setState({ count: count + 1 });
  };
}

//Hooks
const CounterButton = props => {
  const [count, setCount] = useState(0);

  return <button onClick={() => setCount(count + 1)}>{count}</button>;
};

ComponentDidMount

//Class
componentDidMount() {
    console.log('I just mounted!');
}

//Hooks
useEffect(() => {
    console.log('I just mounted!');
}, [])

ComponentWillUnmount

//Class
componentWillUnmount() {
    console.log('I am unmounting');
}

//Hooks
useEffect(() => {
    return () => console.log('I am unmounting');
}, [])

ComponentWillReceiveProps \ ComponentDidUpdate

//Class
componentWillReceiveProps(nextProps) {
    if (nextProps.count !== this.props.count) {
        console.log('count changed', nextProps.count);
    }
}

//Hooks
useEffect(() => {
    console.log('count changed', props.count);
}, [props.count])
//Class
componentDidUpdate() {
    console.log('Just updated..');
}

//Hooks
useEffect(() => {
    console.log('Just updated...');
})

DOM refs

//Class
class InputWithFocus extends React.Component {
  this.inputRef = null;

  render() {
    return (
      <>
        <input
          ref={inputRef => {
            this.inputRef = inputRef;
          }}
        />
        <button onClick={() => this.inputRef.focus()}>Focus the input</button>
      </>
    );
  }
}

//Hooks
const InputWithFocus = props => {
  const inputRef = useRef();

  return (
    <>
      <input ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus the input</button>
    </>
  );
};

this.myVar

const Timer = props => {
  const intervalRef = useRef();

  useEffect(() => {
    const id = setInterval(() => {
      // ...
    });
    intervalRef.current = id;
    return () => {
      clearInterval(intervalRef.current);
    };
  });
};

Comparing with the previous state\props

const Counter = props => {
  const [count, setCount] = useState(0);

  const prevCountRef = useRef();
  useEffect(() => {
    prevCountRef.current = count;
  });
  const prevCount = prevCountRef.current;

  return (
    <h1>
      Now: {count}, before: {prevCount}
    </h1>
  );
};

ShouldComponentUpdate

//Class
shouldComponentUpdate(nextProps) {
    return nextProps.count !== this.props.count
}

//memo
import React, { memo } from 'react';

const MyComponent = memo(
    _MyComponent,
    (prevProps, nextProps) => nextProps.count !== prevProps.count
)

Bound function (callbacks)

//Class (method 1)
constructor(props) {
    super(props)
    this.myCallBack = this.myCallBack.bind(this)
}

//Class (method 2, better)
myCallBack = (props) => {
    this.props.doSomething()
}

//hook way

// if you want callback to be refreshed by props.doSomething changes:
function MyComponent(props) {
    useCallback(() => {
        props.doSomething()
    }, [props.doSomething()])
}


// if you want callback to be take into account state value
// (otherwise it won't know about upper scope state values, it will just know state value at mount - not current one -):
function MyComponent(props) {
    const [someValue, setSomeValue] = useState('');

    useCallback(() => {
        props.doSomething(someValue)
    }, [someValue])
}
@DBattou
Copy link

DBattou commented Mar 13, 2019

Hi, thanks @MacKentoch !!!!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment