目录
在React中有自带的hooks,也可以自己定义自定义hooks,所有的hooks都是以use开头–useXxx
react-hook的学习(常用的useState,useEffect,useRef,useMemo)链接
useState(管理数据)
解决了React函数组件中没有状态的问题(相当于vue里的date)
const FuntionComponent = () => {
// 如果想要设置相关的变量存储数据使用useState。useState调用后返回的是一个数组
// state 和 setState是自定义的名字 例如: a setA b setB
const [state, setState] = useState("默认值")//本质是解构
return (
<div>
{state}
<button onClick={() => setState('新的数据')}></button>
</div>
)
}
export default FunctionComponent
注意:随着代码复杂的提高会遇到的问题
* state
* - state实际就是一个被React管理的变量
* 当我们通过setState()修改变量的值时,会触发组件的自动重新渲染
* - 只有state值发生变化时,组件才会重新渲染
* - 当state的值是一个对象时,修改时是使用新的对象去替换已有对象
* - 当通过setState去修改一个state时,并不表示修改当前的state
* 它修改的是组件下一次渲染时state值
* - setState()会触发组件的重新渲染,它是异步的
* 所以当调用setState()需要用旧state的值时,一定要注意
* 有可能出现计算错误的情况
* 为了避免这种情况,可以通过为setState()传递回调函数的形式来修改state值
const [counter, setCounter] = useState(1);
const addHandler = () => {
setTimeout(() => {
问题:连续点击两次值应该加2,但是只加一(原因在上面)
// setCounter(counter + 1); // 将counter值修改为2
setCounter((prevCounter)=>{//prevCounter是最新的counter
/*
* setState()中回调函数的返回值将会成为新的state值
* 回调函数执行时,React会将最新的state值作为参数传递
* */
return prevCounter + 1;
});
//简写 setCounter(prevState => prevState + 1);
}, 1000);
prevState是React的前一个State(状态) 。
可以用来取反实现项目需求
React Hook 中 useState 异步回调获取不到最新值及解决方案
useRef(获取节点)
获取原生的DOM对象
* 1.可以使用传统的document来对DOM进行操作
* 2.直接从React处获取DOM对象 (组件不会重新渲染,和useState中对数据改变有区别)
* 步骤:
* 1.创建一个存储DOM对象的容器
* - 使用 useRef() 钩子函数
* 钩子函数的注意事项:
* ① React中的钩子函数只能用于函数组件或自定义钩子
* ② 钩子函数只能直接在函数组件中调用
* 2.将容器设置为想要获取DOM对象元素的ref属性
* <h1 ref={xxx}>....</h1>
* - React会自动将当前元素的DOM对象,设置为容器current属性
*
* useRef()
* - 返回的就是一个普通的JS对象
* - {current:undefined}
* - 所以我们直接创建一个js对象,也可以代替useRef()
* - 区别:
* 我们创建的对象,组件每次重新渲染都会创建一个新对象
* useRef()创建的对象,可以确保每次渲染获取到的都是同一个对象
* - 当你需要一个对象不会因为组件的重新渲染而改变时,就可以使用useRef()
App.js
import { useRef, useState } from "react";
const App = () => {
const h1Ref = useRef(); // 创建一个容器
const [count, setCount] = useState(1);
const clickHandler = () => {
//* 通过id获取h1节点
const header = document.getElementById('header');
// header.innerHTML = '哈哈';
//console.log("ID获取dom节点", h1Ref);
//*useRef获取h1节点
console.log("useRef获取dom节点", h1Ref.current);
alert(h1Ref.current === header);//true
h1Ref.current.innerText = '嘻嘻!';/不推荐通过操作dom节点改变页面,脱离了React思想
};
return <div className={'app'}>
<h1 id="header" ref={h1Ref}>我是标题{count}</h1>
<button onClick={clickHandler}>1</button>
</div>;
};
// 导出App
export default App;
useEffect(包含生命周期)
这个hook包含了created updated destroyed
三个生命周期钩子函数
这个hook在一个组件中可以调用多次,所以尽可能将不同的请求放在不同的useEffect
created
function FunctionComponent () {
useEffect(() => {
// 这个函数只会执行一次
}, [])
}
updated(watch)
function FunctionComponent () {
useEffect(() => {
// 一旦数组中的值发生了改变,则会触发函数
}, [相关state的名字, 可以写多个])
}
destroyed
function FunctionComponent () {
useEffect(() => {
return () => {
// 这个函数会在组件被销毁时执行
}
}, [])
}
ReactRouter Hooks
useParams
用来获取动态路由参数(vue this.$router.params)
import { useParams } from ‘react-router-dom’
const FuntionComponent = () => {
// 这个参数名和设置的动态路由的参数名一致 useParams调用后就是一个对象
const { 参数名 } = useParams()
}
useLocation
可以获取路由相关信息
import { useLocation } from 'react-router-dom'
const FuntionComponent = () => {
const location = useLocation()
}
useHistory
可以控制路由的跳转(相当于vue的编程式导航)
import { useHistory } from 'react-router-dom'
const FuntionComponent = () => {
const history = useHistory()
/
history.push('') 可以进行页面跳转
history.replace("") 跳转页面,会替换最新的记录
history.go()
/
}
自定义hooks
react允许我们自己定义相关的hook,但是需要已 use
开头
useQuery
我们自定义的hook可以用来获取query参数
function useQuery () {
return new URLSearchParams(useLocation().search)
}
useQuery().get('参数')