Hook vs Class

Class写法和Hooks比较

State

//Class
class CounterButton extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    }
  }
  render() {
    return <button onClick={() => this.setState({ count: this.state.count + 1 })}>
      { this.state.count }
    </button>
  }
}

//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
//Printing 1st iteration:
useEffect(() => {
  console.log('count changed', props.count);
}, [props.count])

//Skipping first iteration (exactly like componentWillReceiveProps):
const isFirstRun = useRef(true);
useEffect (() => {
  if (isFirstRun.current) {
    isFirstRun.current = false;
    return;
  }
  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 {
  constructor() {
    super();
    this.inputRef = null;
  }
  render() {
    return <div>
      <input ref={inputRef => { this.inputRef = inputRef }} />
      <button onClick={() => this.inputRef.focus()}>
        Focus the input
      </button>
    </div>
  }
}

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

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

this.myVar

useRef除了DOM引用之外还有另一种用法,它的current属性是可变的,可以存储任何值,并且更新current的值时不会引发更新,功能方面类似于this对象。

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

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

上次的状态和当前的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, 
    // Notice condition is inversed from shouldComponentUpdate
    (prevProps, nextProps) => nextProps.count === prevProps.count
)

或者使用useMemo

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

参考文档

原文地址:https://www.cnblogs.com/songyaqi/p/13138910.html