react hook 官网地址:https://react.docschina.org/docs/hooks-intro.html
函数式组件:
const App=()=>{ renturn ( <div><div/>) }
函数式组件特点:1.没有state放数据 2.没有生命周期 3.没有this指向问题
hook主要是服务于函数是组件的,常用的hook有:
1.useState
import { useState } from 'react'
function App1() {
// const [变量名, 修改变量的方法] = useState(变量的初始值)
const [num, setNum] = useState(0)
function btnClick(){
// setNum的作用是将最新的一个值赋值给num
setNum(num+1)
}
return (
<div>
<h1>{num}</h1>
<button onClick={btnClick}>累加</button>
</div>
)
}
export default App1;
2.useEffect(相当于三个生命周期 componentDidMount + componentDidUpdate + componentWillUnmount useEffect可以检测数据更新 )
useEffect(callback,Array)有两个参数 如果Array的[]代表不检测任何数据
/useEffect包含了三个声明周期 其中一个是销毁的生命周期 第二参数不写的时候只检测return里面销毁的的数据 如果写第二个参就不要写return import { useEffect } from 'react'
(函数式组件中写下面这一段)
useEffect(() => {
console.log('数据更新了');
return () => {
console.log('组件销毁了');
}
}, [])
3.useContext 和createContext(使用上下文和创建上下文)
import React from 'react'
// 引入这三个hook
import { useState, createContext, useContext } from 'react'
//创建上下文
const NumContext = createContext()
// 创建子组件
function Child() {
// 使用上下文
const num = useContext(NumContext)
// console.log(useContext(NumContext));
return <h1>{num}</h1>
}
export default function App1() {
const [num, setNum] = useState(100)
return (
<div>
<NumContext.Provider value={num}>
<Child />
</NumContext.Provider>
<button onClick={() => setNum(num + 1)}>累加</button>
</div>
)
}//全局创建上下文(const NumContext = createContext()) ==>全局上下文父组件中包裹子组件( <NumContext.Provider value={num}> <Child /> </NumContext.Provider> 提供器传递参数必须是value)==>子组件使用上下文( const num = useContext(NumContext) 标签内使用 <h1>{num}</h1>)
3.1createContext(使用上下文和创建上下文)
import React from 'react'
import { useState, createContext } from 'react'
const NumContext = createContext()
function Child() {
return (
<NumContext.Consumer>
{
num => <h1>{num}</h1>
}
</NumContext.Consumer>
)
}
function App2() {
const [num, setNum] = useState(0)
return (
<div>
{/* 相当于react-redux里面的提供器 */}
<NumContext.Provider value={num}>
<Child />
</NumContext.Provider>
<button onClick={() => setNum(num + 1)}>累加</button>
</div>
)
}//提供器传递参数(Provider )===>消费器使用(Consumer 函数的形式使用)
export default App2
4.useReducer(useReducer结合usecontext实现redux)
import React from 'react'
// 引入这三个hook
import { createContext, useContext, useReducer } from 'react'
//创建上下文
const NumContext = createContext()
// 创建子组件
function Child() {
// 使用上下文
const { state } = useContext(NumContext)
// console.log(useContext(NumContext));
return <h1>{state.num}</h1>
// {state.data.name}
}
// 创建组件
function Dispatch() {
const { dispatch } = useContext(NumContext)
return (
<button onClick={() => dispatch({ type: 'addFn', value: 10 })}>累加</button>
)
}
function numReducer(state, action) {
let newState = JSON.parse(JSON.stringify(state))
switch (action.type) {
case "addFn":
newState.num += action.value
break;
default:
break;
}
return newState
}
export default function App1() {
// 从useReducer这个hook结构出这两个对象useReducer(第一个参数是函数,第二个参数是传递初始的值或者信息)
const [state, dispatch] = useReducer(numReducer, { num: 0, data: { name: '你好世界' } })
// console.log(useReducer(numReducer, { num: 0 }));
return (
<div>
{/* // Provider的value属性,有两种传递参数的形式,第一种是直接传值,第二种是以对象的形式传值 */}
<NumContext.Provider value={{ state, dispatch }}>
<Child />
<Dispatch />
</NumContext.Provider>
</div>
)
}
5.useRef
import React from 'react'
import { useRef } from 'react'
export default function App4() {
// 一开始给null的原因是不知道把ref给那个元素
const element = useRef(null)
return (
<div>
{/* 没有input的value值没有放在state里面的是不受控组件 */}
<input type="text" ref={element} />
<button onClick={() => console.log(element.current.value)}>按钮</button>
</div >
)
}
Fragment和空标签(react中按需引入)
<ul>
{
// eslint-disable-next-line
this.state.arr.map((item, index) => {
return <Fragment key={index}>
<h1>{item}</h1>
</Fragment>
})
}
</ul>
// Fragment这个hook作用主要是当你想要循环的时候比如又不想要li标签 但是循环又需要key属性的时候可以只用Fragment 但是只能是key 放类名之类的是无效且会报错 空标签无法写属性
错误边界
PureComponent(能够监听子组件和父组件里面的props和state的变化 相当于生命周期内判断和上一个是否相等不相等就返回false相等就返回true不往下执行)
高阶组件HOC:本质是函数(高阶组件就是函数里面返回组件)
import React, { Component } from 'react'
// 创建两个低阶的组件
class Sub1 extends Component {
render() {
return (
<h1>{this.props.num}</h1>
)
}
}
class Sub2 extends Component {
// state = {
// num: 1
// }
render() {
return (
<h1>{this.props.num}</h1>
)
}
// componentDidMount() {
// setTimeout(() => {
// this.setState({
// num: 4
// })
// }, 4000)
// }
}
// 高阶组件HOC本质是一个函数 高阶组价就是函数里返回组件
// 高阶函数是函数里面返回函数
const HocFn = (Comp, timeout, mynum) => {
return (
// 高阶函数里面规定函数名可以不写
class extends Component {
state = {
num: 1
}
render() {
return (
<Comp num={this.state.num} />
)
}
componentDidMount() {
setTimeout(() => {
this.setState({
num: mynum
})
}, timeout)
}
}
)
}
const Sub1Fn = HocFn(Sub1, 2000, 100)
const Sub2Fn = HocFn(Sub2, 2000, 200)
export default function App7() {
return (
<div>
<Sub1Fn></Sub1Fn>
<hr />
<Sub2Fn></Sub2Fn>
</div>
)
}
高阶函数HOF:本质是函数(高阶组件就是函数里面返回函数)
懒加载loadlazy和suspense一起使用
1.创建一个子组件和一个父组件
2.父组件中constSub=React.lazy(()=>import('.子组件路径'));
3.react中引入suspense
4.父组件中<Suspense fallback={<div>loading...</div>}> <子组件/> </Suspense>