npx是什么?
- 避免安全全局模块
Hook规则
- 只在最顶层使用Hook
- 只在React函数中调用Hook
定义函数组件

javascript
interface IHelloProps {
message?: string
}
// const Hello = (props: IHelloProps) => {
// return (
// <div>
// <h1>{props.message}</h1>
// </div>
// )
// }
const Hello: React.FC<IHelloProps> = (props) => {
return (
<div>
<h1>{props.message}</h1>
</div>
)
}
export default Hello
hook的学习
老的hook
- componetDidMount()
- componetDidUpdate()
- componetUnMonunt()
新的Hook完全拥抱函数。
State Hook
在函数组件内部使用hook
- 改变组件状态,组件里面记住状态的值。
javascript
import React, {useState} from "react";
const LikeButton: React.FC = () => {
const [obj, setObj] = useState({like: 0, on: true})
return (
<>
<button onClick={() => setObj({like: obj.like + 1, on: obj.on})}>
{obj.like}👍
</button>
<button onClick={() => setObj({like: obj.like, on: !obj.on})}>
{obj.on ? 'ON' : 'OFF'}
</button>
</>
)
}
export default LikeButton
Effect Hook
- 无需清除的Effect
- 使用useEffect完成标题的更新
- 在老的class 中使用DiaMount 和 DidUpdate两个方法里面执行。
useEffect 在每次dom模型渲染之后,都会执行触发。
javascript
useEffect(() => {
document.title = `点击了${obj.like}次`
});
需要清除的Effect
注册的dom事件,要及时清除,否则会在组件每次渲染的时候,都会注册一次。
javascript
import {useEffect, useState} from "react";
const MouseTracker: React.FC = () => {
const [positions, setPositions] = useState({x: 0, y: 0})
useEffect(() => {
console.log('add effect:', positions.x)
const updateMouse = (e: MouseEvent) => {
console.log("inner")
setPositions({x: e.clientX, y: e.clientY})
}
document.addEventListener('click', updateMouse)
return () => {
console.log('remove effect:', positions.x)
document.removeEventListener('click', updateMouse)
}
});
console.log('before render', positions.x)
return (
<p>鼠标位置:{positions.x}, {positions.y}</p>
)
}
export default MouseTracker;
控制useEffect 的执行
可以使用最后一个参数数组[], 控制useEffect的执行时机,只有这些值发生变化,才会重新执行一次useEffect()
javascript
useEffect(() => {
console.log('add button effect:', obj.like)
document.title = `点击了${obj.like}次`
}, [obj.like, on]);
自定义Hook
自定义hooks,必须以use开头。然后可以在多个组件中引入,互不干扰。
javascript
import {useEffect, useState} from "react";
const useMousePosition = () => {
const [positions, setPositions] = useState({x: 0, y: 0})
useEffect(() => {
console.log('add use effect:', positions.x)
const updateMouse = (e: MouseEvent) => {
console.log("use inner")
setPositions({x: e.clientX, y: e.clientY})
}
document.addEventListener('mousemove', updateMouse)
return () => {
console.log('remove use effect:', positions.x)
document.removeEventListener('mousemove', updateMouse)
}
}, []);
return positions
}
export default useMousePosition
在其它组件中使用:
- 导入
import useMousePosition from ".../hooks/useMousePosition"; - 使用里面的值
const positions = useMousePosition()
HOC 高阶组件(不太好的组件)
- 可以对已有的组件进行转换成新组件。
- 本身是一个函数,接收一个函数,返回另一个函数。
自定义hook完成HOC类似功能(更简单)
自定义:useURLLoader 功能。
javascript
import axios from 'axios'
import {useEffect, useState} from "react";
const useURLLoader = (url: string, deps: any[] = []) => {
const [data, setData] = useState<any>(null)
const [loading, setLoading] = useState<boolean>(false)
useEffect(() => {
setLoading(true)
axios.get(url).then(result => {
setData(result.data)
setLoading(false)
})
}, deps);
return [data, loading]
}
export default useURLLoader
interface IShowResult {
message: string
status: string
}
通过count 控制组件再次重新请求
const [data, loading] = useURLLoader('https://dog.ceo/api/breeds/image/random', [count])
// data 是any 类型,强制转化成IShowResult
const dogResult = data as IShowResult
useRef(改变ref里面的current值,不会重新渲染dom)
修改Ref不会触发组件的重新渲染。
- 使用用 ref 引用一个值
- 通过 ref 操作 DOM
- 避免重复创建 ref 的内容
特点:
- 改变 ref.current 属性时,React 不会重新渲染组件。 所以不适合保存期望展示在屏幕上的信息。
- 可以在 Effect 中读取和写入 ref
- 可以在事件处理程序中读取和写入 ref
- 不要在渲染期间写入或者读取 ref.current
javascript
const likeRef = useRef(0)
- current 泛型的T
function handleAlertClick() {
setTimeout(() => {
alert(`点击了${likeRef.current}次`)
}, 3000)
}
useRef 可以模拟操作dom
javascript
const domRef = useRef<HTMLInputElement>(null)
useEffect(() => {
if(domRef && domRef.current){
domRef.current.focus()
}
});
<input type="text" ref={domRef}/>