一、State

步骤

  1. 导入useState
  1. import React, {useState} from "react"
  1. 声明State
  1. let [value, setValue] = useState(0)

数组第一个参数为使用的值,第二个参数为设置值的函数。useState的参数为默认值。

  1. 使用值
  1. <div>
  2. <span>{value}</span>
  3. </div>
  1. 设置值、
  1. setValue(value + 1)

参数即为对值得变更操作

代码示例

  1. import React, { useState } from "react";
  2. function App() {
  3. let [value, setValue] = useState(0);
  4. const add1 = () => {
  5. setValue(value + 1);
  6. };
  7. return (
  8. <div>
  9. <span>{value}</span>
  10. <button onClick={add1}>+1</button>
  11. </div>
  12. );
  13. }
  14. export default App;

二、useReducer

步骤

  1. 导入useReducer
  1. import { useReducer } from "react"
  1. 创建初始值
  1. const initial = {
  2. n: 0
  3. }
  1. 创建所有操作类型
  1. const reducer = (state, action) => {
  2. if (action.type === "add") {
  3. return { n: state.n + action.number }
  4. } else if (action.type === 'multi') {
  5. return { n: state.n - action.number }
  6. } else {
  7. throw new Error("未知类型")
  8. }
  9. }
  1. 使用useReducer,获得读写操作
  1. const [state, dispatch] = useReducer(action, initial)

  1. <div>{state.n}</div>

  1. dispath(type: "add", numer: 1 )

代码示例

  1. import React from "react"
  2. import { useReducer } from "react"
  3. const initial = {
  4. n: 0
  5. }
  6. const reducer = (state, action) => {
  7. if (action.type === 'add') {
  8. return { n: state.n + action.number }
  9. } else if (action.type = "multi") {
  10. return { n: state.n - action.number }
  11. } else {
  12. throw new Error("未知类型")
  13. }
  14. }
  15. const DemoUseReducer = () => {
  16. const [state, dispatch] = useReducer(reducer, initial)
  17. const add = () => {
  18. dispatch({ type: "add", number: 1 })
  19. }
  20. return (
  21. <>
  22. <div>{state.n}</div>
  23. <button onClick={add}>+1</button>
  24. <button onClick={() => dispatch({ type: "multi", number: 3 })}>-3</button>
  25. </>
  26. )
  27. }
  28. export default DemoUseReducer

三、useContext

步骤

  1. 导入createContext、useContext
  1. import React, { useState, createContext, useContext } from "react"
  1. 创建Context
  1. const Context = createContext(null)
  1. 设置作用域,传递你需要使用的数据
  1. return (
  2. <Context.Provider value={{n, setN}}>
  3. <Father/>
  4. <Son/>
  5. </Context.Provider>
  6. )
  1. 在作用域中的组件解构传递的数据

Father

  1. const {n, setN} = useContext(Context)
  1. 使用解构出来的数据

Father

  1. <button onClick={()=>setN(n=>n+1)}>+1</button>

代码示例

  1. import React, { useState, createContext, useContext } from "react"
  2. const Context = createContext(null)
  3. const DemoUseContext = () => {
  4. const [n, setN] = useState(0)
  5. return (
  6. <Context.Provider value={{ n, setN }}>
  7. <Father />
  8. <Son />
  9. </Context.Provider>
  10. )
  11. }
  12. const Father = () => {
  13. const { n, setN } = useContext(Context)
  14. return (
  15. <>
  16. <div>我是爸爸{n}</div>
  17. <button onClick={() => setN(n => n + 1)}>爸爸按钮+1</button>
  18. </>
  19. )
  20. }
  21. const Son = () => {
  22. const { n, setN } = useContext(Context)
  23. return (
  24. <>
  25. <div>我是儿子{n}</div>
  26. <button onClick={() => setN(n => n - 1)}>儿子按钮-1</button>
  27. </>
  28. )
  29. }
  30. export default DemoUseContext

四、useEffect和useLayoutEffect

步骤

  1. 导入
  1. import { useEffect, useLayoutEffect } from "react"
  1. 每次都执行
  1. useEffect(()=>{})
  1. 第一次渲染执行
  1. useEffect(()=>{},[])
  1. 在某个值变化的时候执行
  1. useEffect(()=>{},[n])
  1. 在页面渲染前执行
  1. useLayoutEffect(()=>{})

代码示例

  1. import React, {useState, useEffect, useLayoutEffect} from "react"
  2. const DemoUseEffect = () => {
  3. const [display, setDisplay] = useState(true)
  4. const [n, setN] = useState(0)
  5. useEffect(() => {
  6. console.log("我每次都执行")
  7. })
  8. useEffect(() => {
  9. console.log("我只在第一次执行")
  10. return () => {
  11. console.log("我只在销毁的时候执行")
  12. }
  13. }, [])
  14. useEffect(() => {
  15. console.log("我只在n变化执行")
  16. }, [n])
  17. useLayoutEffect(() => {
  18. console.log("我是在页面渲染前就执行结束")
  19. })
  20. return (
  21. <>
  22. {display ? <div>{n}</div> : null}
  23. <button onClick={() => setN(n => n + 5)}>+5</button>
  24. <button onClick={() => {
  25. setDisplay(display => !display)
  26. }}>消灭n
  27. </button>
  28. </>
  29. )
  30. }
  31. export default DemoUseEffect

五、memo&useMemo&useCallback

步骤

  1. 导入
  1. import React, {useMemo, useState, memo, useEffect, useCallback} from "react"
  1. memo包住不需要重新渲染的组件函数
  1. const Childer = memo((props) => {
  2. console.log("我是孩子,我不想执行")
  3. return (
  4. <>
  5. <div>我是孩子 {props.childer}</div>
  6. </>
  7. )
  8. })
  1. useMemo包住防止因对象地址变化而导致的误渲染
  1. const childClick = useMemo(() => {
  2. return () => {
  3. }
  4. }, [childer])

代码示例

  1. import React, {useMemo, useState, memo, useEffect, useCallback} from "react"
  2. const DemoUseMemoAndUseCallback = () => {
  3. const [n, setN] = useState(0)
  4. const [childer, setChilder] = useState(0)
  5. useEffect(() => {
  6. console.log("我变化了")
  7. }, [n])
  8. // 使用useMemo阻止因为对象地址变化而重新执行
  9. const childClick = useMemo(() => {
  10. return () => {
  11. }
  12. }, [childer])
  13. // 等同于useMemo,比useMemo简单
  14. const childClick2 = useCallback(() => {
  15. })
  16. return (
  17. <>
  18. <div>{n}</div>
  19. <Childer childer={childer} childClick={childClick} childClick2={childClick2}/>
  20. <button onClick={() => setN(n => n + 10)}>+10</button>
  21. </>
  22. )
  23. }
  24. // 使用memo阻止子组件state没改变,因父组件属性改变而重新渲染
  25. const Childer = memo((props) => {
  26. console.log("我是孩子,我不想执行")
  27. return (
  28. <>
  29. <div>我是孩子 {props.childer}</div>
  30. </>
  31. )
  32. })
  33. export default DemoUseMemoAndUseCallback

六、useRef

步骤

  1. 导入
  1. import { useRef } from "react"
  1. 声明变量
  1. const count = useRef(0)
  1. 使用/修改值
  1. count.current += 1

代码示例

  1. import React, {useEffect, useRef, useState} from "react"
  2. const DemoUseRef = () => {
  3. const count = useRef(0)
  4. const [n, setN] = useState(0)
  5. useEffect(() => {
  6. count.current += 1
  7. console.log("第" + count.current + "执行")
  8. })
  9. return (
  10. <>
  11. <div>{n}</div>
  12. <button onClick={() => setN(n => n + 1)}>n+1</button>
  13. </>
  14. )
  15. }
  16. export default DemoUseRef

七、useImperativeHandle

步骤

  1. 导入
  1. import { useImperativeHandle } from "react"
  1. 在父组件创建ref
  1. const buttonRef = useRef()
  1. 传递给子组件
  1. <button ref={buttonRef}>按钮</button>
  1. 子组件接收并对ref进行修改后返还出去
  1. useImperativeHandle(ref, ()=>{
  2. return {
  3. x: ()=>console.log(1)
  4. }
  5. })

代码示例

  1. import React, {forwardRef, useRef, useEffect, useImperativeHandle} from "react"
  2. const DemoImperativeHandle = () => {
  3. const buttonRef = useRef()
  4. useEffect(() => {
  5. console.log(buttonRef)
  6. })
  7. return (<>
  8. <Son ref={buttonRef} onClick={() => console.log(buttonRef.current.x())}>按钮</Son>
  9. </>)
  10. }
  11. const Son = forwardRef((props, ref) => {
  12. const realRef = useRef()
  13. useImperativeHandle(ref, () => {
  14. return {
  15. x: () => {
  16. console.log(1)
  17. },
  18. ref: realRef
  19. }
  20. })
  21. return (<>
  22. <button ref={realRef} {...props}/>
  23. </>)
  24. })
  25. export default DemoImperativeHandle

八、forwardRef

步骤

  1. 导入
  1. import { forwardRef, useRef } from "react"
  1. 创建ref
  1. const ref = useRef(null)
  1. 向组件传ref
  1. <ChildNode ref={ref}>按钮</ChildNode>
  1. 使用forwardRef接收ref
  1. const ChildNode = forwardRef((props, ref) => {
  2. return (
  3. <>
  4. <button ref={ref} onClick={() => console.log(ref)}>{props.children}</button>
  5. </>
  6. )
  7. })

代码示例

  1. import React, {forwardRef, useRef} from "react"
  2. const DemoForwardRef = () => {
  3. const ref = useRef(null)
  4. return (
  5. <>
  6. <div>我是本身的元素</div>
  7. <ChildNode ref={ref}>按钮</ChildNode>
  8. </>
  9. )
  10. }
  11. const ChildNode = forwardRef((props, ref) => {
  12. return (
  13. <>
  14. <button ref={ref} onClick={() => console.log(ref)}>{props.children}</button>
  15. </>
  16. )
  17. })
  18. export default DemoForwardRef

拓展一、useContext&useReducer代替Redux

步骤

  1. 创建Store数据仓库
  1. cosnt store = {user: null, books: null, movies}
  1. 创建reducer行为操作列表
  1. const reducer = (state, action) => {
  2. switch (action.type) {
  3. case "setUser":
  4. return {...state, user: action.user}
  5. case "setBooks":
  6. return {...state, books: action.books}
  7. case "setMovies":
  8. return {...state, movies: action.movies}
  9. default:
  10. throw new Error("位置类型")
  11. }
  12. }
  1. 创建Context
  1. const Context = createContext(null)
  1. 创建读写的API
  1. const [state, dispatch] = useReducer(reducer, store)
  1. 定义作用域
  1. <Context.Provider value={{state, dispatch}}>
  2. <User/>
  3. <Books/>
  4. <Movies/>
  5. </Context.Provider>
  1. 使用传递的数据
  1. const {state, dispatch} = useContext(Context)
  1. 对数据进行操作

  1. <div>{state.user.name}</div>

  1. dispatch({type: "setUser", user: 数据})

代码示例

  1. import React, {useContext, useEffect, useReducer, createContext} from "react"
  2. // 数据仓库
  3. const store = {
  4. user: null,
  5. books: null,
  6. movies: null
  7. }
  8. // 行为类型
  9. const reducer = (state, action) => {
  10. switch (action.type) {
  11. case "setUser":
  12. return {...state, user: action.user}
  13. case "setBooks":
  14. return {...state, books: action.books}
  15. case "setMovies":
  16. return {...state, movies: action.movies}
  17. default:
  18. throw new Error("位置类型")
  19. }
  20. }
  21. // 创建Context
  22. const Context = createContext(null)
  23. const DemoContextReducer = () => {
  24. // 创建数据读写的API
  25. const [state, dispatch] = useReducer(reducer, store)
  26. return (
  27. <Context.Provider value={{state, dispatch}}>
  28. <User/>
  29. <Books/>
  30. <Movies/>
  31. </Context.Provider>
  32. )
  33. }
  34. const User = () => {
  35. const {state, dispatch} = useContext(Context)
  36. useEffect(() => {
  37. ajax("/user").then(user => {
  38. dispatch({type: "setUser", user})
  39. console.log(user)
  40. })
  41. }, [])
  42. return (
  43. <>
  44. <h3>姓名</h3>
  45. {state.user ? <div>{state.user.name}</div> : null}
  46. </>
  47. )
  48. }
  49. const Books = () => {
  50. const {state, dispatch} = useContext(Context)
  51. useEffect(() => {
  52. ajax("/books").then(books => {
  53. dispatch({type: "setBooks", books})
  54. })
  55. }, [])
  56. return (
  57. <>
  58. <h3>书籍</h3>
  59. {state.books ? state.books.map(book => (<div key={book.id}>{book.name}</div>)) : null}
  60. </>
  61. )
  62. }
  63. const Movies = () => {
  64. const {state, dispatch} = useContext(Context)
  65. useEffect(() => {
  66. ajax("/movies").then(movies => {
  67. dispatch({type: "setMovies", movies: movies})
  68. })
  69. }, [])
  70. return (
  71. <div>
  72. <h3>电影</h3>
  73. {state.movies ? state.movies.map(item => <div key={item.id}>{item.name}</div>) : null}
  74. </div>
  75. )
  76. }
  77. export default DemoContextReducer
  78. // 模拟请求数据
  79. function ajax(path) {
  80. return new Promise((resolve, reject) => {
  81. setTimeout(() => {
  82. if (path === "/user") {
  83. resolve({
  84. id: 1,
  85. name: "梁又文"
  86. })
  87. } else if (path === "/books") {
  88. resolve([{
  89. id: 1,
  90. name: "我是一本好书"
  91. }, {
  92. id: 2,
  93. name: "我是一本坏书"
  94. }])
  95. } else if (path === "/movies") {
  96. resolve([{
  97. id: 1,
  98. name: "最时间的尽头"
  99. }, {
  100. id: 2,
  101. name: "八百"
  102. }])
  103. }
  104. }, 3000)
  105. })
  106. }

拓展二、自定义hook

代码示例

useList

  1. import {useState} from "react"
  2. const useList = () => {
  3. const [list, setList] = useState(0)
  4. return ({
  5. list: list,
  6. setList: setList
  7. })
  8. }
  9. export default useList

DemoCustomHook

  1. import React from "react"
  2. import useList from "./hooks/useList"
  3. const DemoCustomHook = () => {
  4. const {list, setList} = useList()
  5. return (
  6. <>
  7. <div>{list}</div>
  8. <button onClick={() => setList(n => n + 10)}>+10</button>
  9. </>
  10. )
  11. }
  12. export default DemoCustomHook