0-6 React函数组件(useState、useEffect、自定义Hook组件)

目录

  • 创建方式
  • 没有state怎么办
  • 没有生命周期怎么办
  • useState的原理

1.创建方式

  • 就是创建一个函数
    组件只是说明能和别人组合起来
const Hello = (props)=>{
    return <div>{props.message}</div>
}
//等价于 箭头函数
const Hello = props => <div>{props.message}</div>
//等价于 普通函数
function Hello(props) {
    return <div>{props.message}</div>
}

2.函数组件代替class组件

  • 特点:写个函数当做标签用,函数名就是标签名。
  • 函数组件的优势
    1.函数更加简单明了,正常的书写代码,不需要很多无用的属性和格式
    ——如:extends、constructor、super、render、this
    2.消除this:直接用变量名,声明也直接 const
    3.唯一思考的:useState(hook API)
import React,{useState,useEffect} from 'react'
const App = props=>{
  //引入了useState就不需要 React.useState ;从useState中获取n和setN
    const [n,setN] = useState(0)
    const onClick = ()=>{
        setN(n+1)
    }
    return (
        <div>
            {n}
            <button onClick={onClick}>+1</button>
        </div>
    )
}

2.1 两个问题

  • 问题一:函数组件没有state
  • 解决:使用 useState
    const [n,setN] = useState(初始值)
    1.这个API是 React v16.8.0 推出的 Hooks API的其中一个
    2.返回两个参数:[读,写]
    3.之所以使用 useState不直接赋值是因为直接赋值那么每次渲染组件进来就会重新赋值,这样n就永远是初始值
  • 问题二:函数组件没有生命周期
  • 解决:使用 useEffect
    1.这个API是 React v16.8.0 推出的 Hooks API的其中一个

2.2 useEffect

  • 作用:模拟生命周期,消除副作用
  • useEffect接收两个参数
    1.函数
    2.数组:该参数控制什么时候调用这个函数
    (默认这个函数在每一次渲染时调用)
  • 当第二个参数为:
    1.[]:在第一次渲染时调用函数(componentDidMount)
    2.[n]:当n发生变化时调用函数(写什么就监听什么),第一次也变,从undefined变成1(componentDidUpdate)
    3.[n,m]:监听两个(componentDidUpdate)
    4.什么都不写:任何一个 state 变化都要执行函数(componentDidUpdate)
    5.useEffect 函数返回的函数是在销毁的时候执行
// 模拟 componentDidMount
useEffect(()=>{
    console.log('use effect')
},[])
// 模拟 componentDidUpdate
useEffect(()=>{
    console.log('use effect')
},[n])
useEffect(()=>{
    console.log('use effect')
},[n,m])
useEffect(()=>{
    console.log('use effect')
})
  • 模拟一个组件消失:if…else…
useEffect(()=>{
    console.log('第一次渲染')
    return ()=>{
    console.log('组件要死了')
    }
})

2.3 其他生命周期模拟

  • constructor
    函数组件执行的时候,return前面的内容就相当于 constructor
  • shouldComponentUpdate
    后面的 React.memo 和 useMemo可以解决
  • render
    函数组件的返回值就是render的返回值

3.自定义hook:useUpdate

  • 注意:规定自定义 hook 一定要 use 开头
  • componentDidUpdate只在第二次渲染的时候才执行
    1.当useEffect模拟它时,n的每一次变化都会被监听
    2.想要完全模拟,第一次不执行,也就是从 undefined 到 初始值不提醒
  • 思路
    1.新建一个中间变量count
    2.n每次变化时,count都+1,count每次变化时都打印出变化
    3.给count加一个判断,只有当count>1时,才调用打印出变化
  • 封装
    1.函数组件的好处:就是函数里面还可以嵌套函数
    2.使用自定义 useUpdate 的时候,传入一个函数和依赖
    3.在自定义组件内部:将组件的依赖传给 useEffect 获取到中间变量 count
    4.再次使用 useEffect,count作为依赖,满足条件时调用函数
  • 使用参数传入的好处
    1.自定义hook可以放到组件外面,不受变量约束
    2.最好放到新的文件中引入即可使用
// useUpdate.js
const useUpdate = (fn,dep)=>{
    const [count,setCount] = useState(0)
    useEffect(()=>{
        //当参数发生改变,count就+1
        setCount(x=>x+1)
    },[dep])  //为了消除警告阉割功能:只支持一个依赖
    
    useEffect(()=>{
        // 当count改变,且count>1时,执行函数fn
        // 实现第一次不打印出log
        if(count>1){
            fn()
        }
    },[count,fn])
}
export default useUpdate 

// 组件中使用
import useUpdate from './useUpdate.js'
useUpdate(()=>{
    // n第一次渲染的时候不会log
    console.log('变了')
},n) //只支持一个依赖

你可能感兴趣的:(前端框架,react.js,前端)