创建方式
const Hello = (props)=>{
return <div>{props.message}</div>
}
const Hello = props => <div>{props.message}</div>
function Hello(props){
return <div>{props.message}</div>
}
函数组件代替Class组件
面临两个问题:
-
函数组件没有State
-
函数组件没有生命周期
React推出了Hooks API,其中的useState和useEffect可以解决这两个问题
依然拿+1的这个案例,首先用class组件写一遍,
可以发现有很多固定的格式写法,实现这样一个简单的功能代码量也比较多。接下来用函数组件写法写一次进行对比。
可以看出从代码复杂程度来看函数组件相比Class组件更加简洁好读一点。
useState
React v16.8.0推出了Hooks API 其中的useState
可以类比class组件的state
const [n, setN] = React.useState(0)
其中useState返回两个API,n用来读,setN用来写(名字可以自定义,前面的用来读后面的用来写),后面跟的参数是初始化state的值图中的webstorm也有提示。
此外函数组件消除了this
useEffect
React v16.8.0推出了Hooks API 其中的useEffect
可以类比class组件的生命周期
模拟componentDidMount
如果直接在函数内定义一个方法,那么它每次更新都会调用,不能做到只有第一次渲染时调用,所以需要用到uesEffect
默认情况下和写在外面差不多,如果需要只是第一次渲染,这时用到useEffect
的第二个参数,写一个空数组即可。
useEffect(()=>{console.log('第一次渲染')},[])
模拟componentDidUpdate
useEffect(()=>{console.log('任意属性变更')})
useEffect(()=>{console.log('n变了')},[n])
比如我想实现在n变化了的时候进行更新,那么
在第二个参数的数组里写入那个监听的变化对象,比如在n变化的时候更新,那么就在数组里写入n
如果数组里面包含了全部的state那么可以省略不写,则是任何state变化了都会对这个方法进行调用
模拟componentWillUnmount
useEffect(()=>{
console.log('第一次渲染')
return ()=>{
console.log('组件要死了')
}
})
用一个新的案例来展示,点击隐藏或显示,隐藏时相当于组件被销毁了。如果我们想模拟组件销毁的生命周期钩子,需要在useEffect
内返回一个函数,这个返回的函数会在组件销毁时运行。
模拟其他的生命周期
constructor
函数组件执行的时候就相当于consturctor
shouldComponentUpdate
运用React.memo
和 useMemo
render
函数组件的返回值就是render
自定义Hook之useUpdate
在模拟componentDidUpdate
时第一次变化也算更新渲染,(比如上述例子的+1变化,因为初始时从undefined变成0也会换变化)为了让其第一次不算更新渲染,我们可以使用一个自定义Hook
声明一个变量用来记录更新次数。用useEffect来实现n变化了更新次数+1。再用useEffect来实现更新次数nUpdateCount变化了且大于1时打印出“变化了”,即可消除初始的渲染提示。
对代码进行重构
实现了自定义Hook
再把这段代码单独放一个文件再引用。