项目创建
使用create-react-app创建项目
(官方文档)
npx create-react-app my-app --template typescript
如果半天没反应,检查npm的源,修改为taobao
npm config get registry
npm config set registry https://registry.npm.taobao.org
npx的作用
- 避免安装全局模块
- 可调用项目内部安装的模块
项目内部安装的模块一般要到node_modules里找到才能执行
例如, 要执行安装的mocha
node_modules/.bin/mocha --version
使用npx可直接执行
npx mocha --version
第一个组件Hello world
interface IHelloProp {
message: string
}
const Hello = (props: IHelloProp) => {
return <h1>{props.message}</h1>
}
export default Hello
如果像上面这样创建一个函数式组件,props丢失了children属性,组件本身也没有给定类型
使用泛型重写组件, 组件有了明确的类型,在编辑器中就能很容易看到它拥有的属性
interface IHelloProp {
message?: string
}
const Hello:React.FunctionComponent<IHelloProp> = (props) => {
return <h1>{props.message}</h1>
}
Hello.defaultProps = {
message: 'Hello world!'
}
export default Hello
React.FunctionComponent 的类型别名 React.FC
interface IHelloProp {
message?: string
}
const Hello:React.FC<IHelloProp> = (props) => {
return <h1>{props.message}</h1>
}
export default Hello
useState
useState用于保存和修改组件状态
import { useState } from "react"
const LikeButton:React.FC = () => {
const [like, setLike] = useState(0)
const [onoff, setOnoff] = useState(true)
return (
<>
<button onClick={()=>{setLike(like + 1)}}>
{like} 👍
</button>
<button onClick={()=>{setOnoff(!onoff)}}>
{onoff ? 'on' : 'off'}
</button>
</>
)
}
export default LikeButton
useEffect
useEffect用于执行副作用函数
如果不传第二个参数,每次渲染页面useEffect都会执行
第二个参数为空数组 [], 则第一次渲染时执行
useEffect(()=>{
document.title = `点击了${like}次`
})
useEffect可以 return 一个清理函数(防止内存泄漏),每次组件卸载时执行清除,或者在下一次useEffect执行前清除
useEffect(()=>{
console.log("I'm in")
const updatePosition = (e: MouseEvent) => {
setPosition({x: e.clientX, y: e.clientY})
}
document.addEventListener('click', updatePosition)
return () => {
console.log("let's remove")
document.removeEventListener('click', updatePosition)
}
})
自定义hook
自定义hook用于将组件逻辑提取到可复用的函数中,hook的本质是函数
- 自定义hook必须以 use 开头
- 两个使用相同自定义hook的组件之间 state 相互独立 ```typescript // 示例 1 import { useState, useEffect } from “react”
const useMousePosition = () => { const [position, setPosition] = useState({x:0, y:0}) useEffect(()=>{
const updatePosition = (e: MouseEvent) => {
setPosition({x: e.clientX, y: e.clientY})}
document.addEventListener('mousemove', updatePosition)
return () => {
document.removeEventListener('mousemove', updatePosition)
}
}, [])
return position
}
export default useMousePosition
```tsx
// 示例 2
import { useEffect, useState } from "react"
import axios from 'axios'
const useURLLoader = (url: string, deps: any[] = []) => {
const [data, setData] = useState<any>(null)
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
setIsLoading(true)
axios.get(url).then(res => {
setData(res.data)
setIsLoading(false)
})
}, deps)
return [
data,
isLoading
]
}
export default useURLLoader
HOC高阶组件 VS 自定义hook
HOC高阶组件就是一个函数,接受一个组件作为参数,返回一个新的组件
HOC会无端端多出我们不需要的东西,比如组件,且难以理解
自定义 hook 比 HOC 简洁高效
Hooks使用规则
- 只在最顶层使用 Hook
- 只在 React 函数中调用 Hook
一个学习hooks用法的网站 useHooks