1.创建方式
const Hello = (props)=>{
return <div>{props.message}</div>
}//1
const Hello = props =><div>{props.message}</div>//2
function Hello(props){
return <div>{props.message}</div>
}//3
2.没有state怎么办
React v16.8.0 推出Hooks API
其中有个API叫做useState
const App = props = {
const [n,setN] = useState(0)//n为读,setN为写
const onClick = () => {
setN(n + 1)
}
return (
<div>
{n}
<button onClick={onClick}>+1</button>
</div>
)
}
3.没有生命周期怎么办
所谓的生命周期就是在特定的函数里做某件事
React v16.8.0 推出 Hooks API
其中一个API叫做useEffect,解决副作用
模拟componentDidMount
import React, { useState, useEffect } from 'react'
// 所有都用箭头函数,消除了this
//模拟componentDidMount
const App = props => {
const [n, setN] = useState(0)
const onClick = () => { setN(n + 1) }
useEffect(() => { console.log('use effect') }, [])
return (
<div>{n}
<button onClick={onClick}>1</button>
</div>
)
}
export default App
模拟componentWillUnmount
import React, { useEffect, useState } from 'react'
// 所有都用箭头函数,消除了this
const App = props => {
const [childVisible, setChildVisible] = useState(true)
const hide = () => {
setChildVisible(!childVisible)
}
const show = () => {
setChildVisible(!childVisible)
}
console.log(!childVisible)
useEffect(() => { console.log('use effect') })
return (
<div>
{childVisible ? <button onClick={hide}>hide</button> : <button onClick={show}>show</button>}
{childVisible ? <Child /> : null}
</div>
)
}
//onClick 只接受函数,不接受函数调用
const Child = (props) => {
useEffect(() => {
return () => {
console.log('Child 销毁了')
}
})
return (<div>Child</div>)
}
export default App
生命周期总结
- 模拟componentDidMount
useEffect(()=>{console.log('第一次渲染'),[]}) - 模拟componentDidUpdate, 在某个东西变化了之后执行的代码,但第一次渲染也会触发
useEffect(()=>{console.log('任意属性变更,后面的数组可以不写')})
useEffect(()=>{console.log('n变了'),[n]}) //依赖于n改变
useEffect(()=>{console.log('n或者m变了'),[n,m]}) - 模拟componentWillUnmount
useEffect(()=>{
console.log('第一次渲染')
return ()=>{
console.log('组件要死了')
}
})
- constructor
函数组件执行的时候,就相当于constructor - shouldComponentUpdate
后面的React.memo和useMemo可以解决 - render
函数组件的返回值就是render的返回值
4.自定义hook之useUpdate
场景:解决对第一次渲染也触发上述模拟componentDidUpdate这个的执行代码,下面三种方式是对这项功能的优化过程,也可以只看useUpdate用法。
第一次由undefined变为0时不执行函数
第二次变化时,执行函数
第三次变化时,执行函数
。。。
实现修改才触发钩子
// 实现修改才触发钩子
import React, { useEffect, useState } from 'react'
const App = props => {
const [n, setN] = useState(0)
const onClick = () => {
setN(n + 1)
}
const [nUpdateCount, setNUpdateCount] = useState(0)
useEffect(() => {
setNUpdateCount((nUpdateCount) => nUpdateCount + 1)
}, [n])
useEffect(() => {
if (nUpdateCount > 1) {
console.log(nUpdateCount)
console.log("修改了n")
}
}, [nUpdateCount])
return (
<div>
{n} <button onClick={onClick}>+1</button>
</div>
)
}
export default App
用组件封装起来
// 实现修改才触发钩子
import React, { useEffect, useState } from 'react'
const App = props => {
const [n, setN] = useState(0)
const onClick = () => {
setN(n + 1)
}
const useX = (n) => {
const [nUpdateCount, setNUpdateCount] = useState(0)
useEffect(() => {
console.log("修改了n")
setNUpdateCount((nUpdateCount) => nUpdateCount + 1)
}, [n])
return { nUpdateCount }
}
const nUpdateCount = useX(n).nUpdateCount
// console.log(nUpdateCount)
useEffect(() => {
if (nUpdateCount > 1) {
console.log("修改了nUpdateCount")
}
}, [nUpdateCount])
return (
<div>
{n} <button onClick={onClick}>+1</button>
</div>
)
}
export default App
引入和使用自定义的useUpdate(最终版)
import React, { useEffect, useState } from 'react'
const useUpdate = (fn, n) => {
const [count, setCount] = useState(0)
// console.log(nUpdateCount)
useEffect(() => {
// console.log("修改了n")
setCount((count) => count + 1)
}, [n])
useEffect(() => {
if (count > 1) {
fn()
}
}, [count, fn])
// 疑问?????依赖fn是控制台提示写的,但是点击按钮就触发了两次
}
const App = props => {
const [n, setN] = useState(0)
const onClick = () => {
setN(n + 1)
}
useUpdate(() => {
console.log("修改了nUpdateCount")
}, n)
return (
<div>
{n} <button onClick={onClick}>+1</button>
</div>
)
}
export default App