目录
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}
</>
)
}