项目创建

使用create-react-app创建项目

(官方文档)

  1. npx create-react-app my-app --template typescript

如果半天没反应,检查npm的源,修改为taobao

  1. npm config get registry
  2. npm config set registry https://registry.npm.taobao.org

npx的作用

  • 避免安装全局模块
  • 可调用项目内部安装的模块

项目内部安装的模块一般要到node_modules里找到才能执行
例如, 要执行安装的mocha

  1. node_modules/.bin/mocha --version

使用npx可直接执行

  1. npx mocha --version

第一个组件Hello world

  1. interface IHelloProp {
  2. message: string
  3. }
  4. const Hello = (props: IHelloProp) => {
  5. return <h1>{props.message}</h1>
  6. }
  7. export default Hello

如果像上面这样创建一个函数式组件,props丢失了children属性,组件本身也没有给定类型
使用泛型重写组件, 组件有了明确的类型,在编辑器中就能很容易看到它拥有的属性

  1. interface IHelloProp {
  2. message?: string
  3. }
  4. const Hello:React.FunctionComponent<IHelloProp> = (props) => {
  5. return <h1>{props.message}</h1>
  6. }
  7. Hello.defaultProps = {
  8. message: 'Hello world!'
  9. }
  10. export default Hello

React.FunctionComponent 的类型别名 React.FC

  1. interface IHelloProp {
  2. message?: string
  3. }
  4. const Hello:React.FC<IHelloProp> = (props) => {
  5. return <h1>{props.message}</h1>
  6. }
  7. export default Hello

useState

useState用于保存和修改组件状态

  1. import { useState } from "react"
  2. const LikeButton:React.FC = () => {
  3. const [like, setLike] = useState(0)
  4. const [onoff, setOnoff] = useState(true)
  5. return (
  6. <>
  7. <button onClick={()=>{setLike(like + 1)}}>
  8. {like} 👍
  9. </button>
  10. <button onClick={()=>{setOnoff(!onoff)}}>
  11. {onoff ? 'on' : 'off'}
  12. </button>
  13. </>
  14. )
  15. }
  16. export default LikeButton

useEffect

useEffect用于执行副作用函数
如果不传第二个参数,每次渲染页面useEffect都会执行
第二个参数为空数组 [], 则第一次渲染时执行

  1. useEffect(()=>{
  2. document.title = `点击了${like}次`
  3. })

useEffect可以 return 一个清理函数(防止内存泄漏),每次组件卸载时执行清除,或者在下一次useEffect执行前清除

  1. useEffect(()=>{
  2. console.log("I'm in")
  3. const updatePosition = (e: MouseEvent) => {
  4. setPosition({x: e.clientX, y: e.clientY})
  5. }
  6. document.addEventListener('click', updatePosition)
  7. return () => {
  8. console.log("let's remove")
  9. document.removeEventListener('click', updatePosition)
  10. }
  11. })

自定义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(()=>{

  1. const updatePosition = (e: MouseEvent) => {
  2. setPosition({x: e.clientX, y: e.clientY})}
  3. document.addEventListener('mousemove', updatePosition)
  4. return () => {
  5. document.removeEventListener('mousemove', updatePosition)
  6. }
  7. }, [])
  8. return position

}

export default useMousePosition

  1. ```tsx
  2. // 示例 2
  3. import { useEffect, useState } from "react"
  4. import axios from 'axios'
  5. const useURLLoader = (url: string, deps: any[] = []) => {
  6. const [data, setData] = useState<any>(null)
  7. const [isLoading, setIsLoading] = useState(true)
  8. useEffect(() => {
  9. setIsLoading(true)
  10. axios.get(url).then(res => {
  11. setData(res.data)
  12. setIsLoading(false)
  13. })
  14. }, deps)
  15. return [
  16. data,
  17. isLoading
  18. ]
  19. }
  20. export default useURLLoader

HOC高阶组件 VS 自定义hook

HOC高阶组件就是一个函数,接受一个组件作为参数,返回一个新的组件
HOC会无端端多出我们不需要的东西,比如组件,且难以理解
自定义 hook 比 HOC 简洁高效

Hooks使用规则

  • 只在最顶层使用 Hook
  • 只在 React 函数中调用 Hook

一个学习hooks用法的网站 useHooks