新版本新特性解读
- render支持返回数组和字符串
return [<div>1</div>,<div>2</div>]
- 错误边界捕获
- 提升SSR渲染速度,支持流式渲染
- 减少文件体积
- 生命周期函数更新
1、由于异步渲染的改动,有可能会导致
componentWillMount,componentWillReceiveProps,componentWillUpdate执行,所以抛弃这三个生命周期函数
2、createContext不必一层层传递,可以指定数据共享范围
3、createRef
4、hooks开发方式更新
hooks出现的意义是什么
- hooks之间状态独立,依赖独立的状态来更新
- 让函数组件有了状态管理
- 解决了组件树不直观、类组件难维护、逻辑不易复用的问题
- react多了第二个参数,依赖特定的参数执行函数
学习hooks的意义是什么
- 高效开发
- 提高组件复用性
- 提高逻辑复用性
- 提升性能
- 实现更复杂的功能
应用场景
- 利用hooks取代生命周期函数
- 让函数组件拥有状态
- 组件辅助函数
- 处理发送请求
- 存取数据
- 做好性能优化
useState
import React, { useState } from "react";
const [name, setName] = userState("");
useEffect(类似于componentDidMount)
import React, { useEffect } from "react";
useEffect(() => {
//2、再执行外面的函数
return () => {
//1、执行一些销毁的内容,先执行
}
},[])//第二个函数是依赖执行的参数列表,无其他列表只执行一次,否则依赖后面参数变化来执行
//执行实际是render之后
useLayoutEffect(类似于componentWillMount)
import React, { useLayoutEffect } from "react";
useLayoutEffect(() => {
},[])//dom更新完成之后执行操作,第二个函数是依赖执行的参数列表,无其他列表只执行一次,否则依赖后面参数变化来执行
// 比useEffect先执行
useMemo
import React, { useMemo } from "react";
const getDoubleNum = useMemo(() => {
console.log('getDoubleNum'); //跟随num改变,缓存2*num
return 2*num
},[num])
return <div onClick={() => {setAge(age+1)}}>这是一个函数组件num:{getDoubleNum}age:{age}</div>
useCallback
const getDoubleNum = useCallback(() => {
console.log('getDoubleNum');
return 2*num
},[num])
return <div onClick={() => {setAge(age+1)}}>这是一个函数组件num:{getDoubleNum()}age:{age}</div>
useMemo跟useCallback对比
- useMemo返回的是一个值
- useCallback返回的是一个函数
- useMemo缓存的是一个值,useCallback缓存的是一个函数
const getDoubleNum = useCallback(() => {
console.log('getDoubleNum');
return 'test'
},[num])
set.add(getDoubleAge)
console.log(set.size);//一直是2,不递增。传到子组件不会带动子组件更新
const getDoubleAge = useMemo( () => {
return age * 2
},[age])
set.add(getDoubleAge)
console.log(set.size);//每次递增传到子组件,会带动子组件依赖函数执行
useRef
保存计时器内容
const timer = useRef()
useEffect(() => {
timer.current = setInterval(() => {
setNum(num => num+1)
},400)
},[])
useEffect(() => {
if(num > 10) {
console.log('超过10秒了');
clearInterval(timer.current)
}
},[num])
useContent(带动子组件内容变化)
const Context = createContext(null)
function StateFunction () {
const [num, setNum] = useState(1)
const [age, setAge] = useState(12)
return <div onClick={() => setNum(num + 1)}>
这是一个函数组件num:{num}
<Context.Provider value={{num,age}}>
<Item1></Item1>
<Item2></Item2>
</Context.Provider>
</div>
}
function Item1() {
const num = useContext(Context);
console.log('num',num);
return <div>子组件{num.num+1}</div>
}
function Item2() {
const num = useContext(Context);
return <div>子组件{num.num +2}</div>
}
export default StateFunction;
useReducer
import React, { useState, useReducer} from "react";
const store = {
num: 1
}
const reducer = (state, action) => {
switch(action.type) {
case "changeNum":
return {
...state,
num: action.num
};
default:
return {
...state
};
}
}
function StateFunction () {
const [state, dispatch] = useReducer(reducer,store);
return <div onClick={() => dispatch({
type: 'changeNum',
num: 100
})}>
这是一个函数组件num:{state.num}
</div>
}
export default StateFunction;
useImperativeHandle
是为了函数组件可以使用ref
import React, { forwardRef, useImperativeHandle, useEffect, useRef } from 'react'
const TestRef = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
open() {
console.log("open")
}
}))
})
function App () {
const ref = useRef()
useEffect(() => {
ref.current.open() //open
},[])
return(
<>
<div>石小阳</div>
<TestRef ref={ref}></TestRef>
</>
)
}
export default App
自定义hooks使用
loadData.js:
import React, {useEffect, useState} from 'react'
function useLoadData() {
const [num, setNum] = useState(1);
useEffect(() => {
setTimeout(() => {
setNum(2)
},1000)
},[])
return [num,setNum]
}
export default useLoadData
使用方:
import useLoadData from './loadData.js';
function StateFunction () {
// const [state, dispatch] = useReducer(reducer,store);
const [num, setNum] = useLoadData();
return <div>
这是一个函数组件num:{num}
</div>
}
export default StateFunction;
抽离useLocalReducer
useLocalReducer.js
import React, { useState, useReducer} from "react";
const store = {
num: 1
}
const reducer = (state, action) => {
switch(action.type) {
case "changeNum":
return {
...state,
num: action.num
};
default:
return {
...state
};
}
}
function useLocalReducer() {
const [state, dispatch] = useReducer(reducer, store);
return [state, dispatch]
}
export default useLocalReducer;
使用方:
import React, { useState, useReducer} from "react";
import useLocalReducer from './useLocalReducer'
function StateFunction () {
// const [state, dispatch] = useReducer(reducer,store);
const [state, dispatch] = useLocalReducer();
return <div onClick={() => { dispatch({
type: 'changeNum',
num: 100
})}}>
这是一个函数组件num:{state.num}
</div>
}
export default StateFunction;
网友评论