-
React的本质?
从Model 到 View 的映射。假设状态永远不变,那么实际上函数组件就相当于是一个模版引擎,只执行一次。
但是React本身正是为了动态的状态变化而设计的,而可能引起状态变化的原因基本只有两个:
-
用户操作产生的事件,比如点击了某个按钮
-
副作用产生的事件,比如发起某个请求正确返回了
例子:一个用于显示博客文章的组件,接收一个文章的id作为参数,然后根据这个id从服务器端获取文章内容并显示,并检测id的变化,重新发送请求。
如果在 class 组件,需要这样实现(用到2个生命周期方法):
class BlogView extends React.Component {
// ...
componentDidMount() {
// 组件第一次加载时去获取Blog数据
fetchBlog(this.props.id)
}
componentDidUpdate(prevProps) {
// 当Blog的id变化时去获取博客文章
if (prevProps.id !== this.props.id) {
fetchBlog(this.props.id)
}
}
}
而在函数组件中,只需要useEffect即可:
function BlogView( {id} ) {
useEffect(() => {
// 当id变化时,重写获取博客文章
fetchBlog(id)
}, [id])
}
如何满足class组件构造函数初始化的功能?
思考下构造函数的本质,在其他代码执行之前的一次性初始化工作。
-即我们要实现的就是,一次性代码执行
我们可以实现useSingleton这样的一次性执行某段代码的自定义hook:
function useSingleton(callback) {
const called = useRef(false)
if (called.current) return
callback()
callback.current = true
}
在一个函数组件中,可以调用这个自定义hook来执行一些一次性的初始化逻辑
const myComp = () => {
useSingleton(() => {
console.log('这段代码只执行一次')
})
return (
<div>...</div>
)
}
对于三种常用的生命周期方法
componentDidMount、componentDidUpdate、componentWillUnmount
useEffect(() => {
console.log('这里基本等价于componentDidMount + componentDidUpdate')
return () => {
console.log('这里基本等价于componentWillUnmount')
}
}, [deps])