用来声明状态变量。

  1. import React, { useState } from 'react';
  2. // ...
  3. const [ count , setCount ] = useState(0);
  4. // ...
  • count 声明的变量
  • setCount 设用来更新变量的函数
  • 0 初始值
  • 多个状态声明不能出现在条件判断语句中

用来代替生命周期函数。

  1. import React, { useEffect } from 'react';
  2. useEffect(()=>{
  3. // some code
  4. })
  • 第一次组件渲染和每次组件更新都会执行这个函数
  • useEffect中的函数的执行不会阻碍浏览器更新视图,这些函数是异步的

使用 useEffect 实现类似 componentWillUnmount

  1. useEffect(()=>{
  2. return () => {
  3. // some code
  4. }
  5. })
  • 返回一个函数实现解绑
  • 但是这样会导致每次状态发生变化,useEffect 都进行解绑
  1. useEffect(()=>{
  2. return () => {
  3. // some code
  4. }
  5. }, [])

使用第二个参数,制定哪些状态发生变化时再解绑

跨越组件层级直接传递变量,实现状态共享。

  • useContext 解决的是组件之间值传递的问题
  • redux 解决的是应用中统一管理状态的问题
  • useContext 通过和 useReducer 的配合使用,可以实现类似 Redux 的作用

Outer 组件

  1. import React, { createContext } from 'react'
  2. const ValueContext = createContext()
  3. function Outer(){
  4. return (
  5. <>
  6. <ValueContext.Provider value={'我是传向 Inner 组件的值'}>
  7. <Inner />
  8. </ValueContext.Provider>
  9. </>
  10. )
  11. }
  12. export default Outer;
  • 使用 createContext 创建 context
  • 使用 createContext 同时生成组件
  • 闭合标签将组件包裹

Inner 组件

  1. import React, { useContext } from 'react'
  2. const value = useContext(CountContext)
  3. function Inner(){
  4. return (
  5. <>
  6. <p>{value}</p>
  7. </>
  8. )
  9. }
  10. export default Inner;

使用 useContext 来使用上下文

用来实现类似 redux 功能

  1. import React, { useReducer } from 'react';
  2. function Demo(){
  3. const [ count, dispatch ] = useReducer((state,action)=>{
  4. switch(action){
  5. case 'add':
  6. return state+1
  7. case 'sub':
  8. return state-1
  9. default:
  10. return state
  11. }
  12. },0)
  13. return (
  14. <>
  15. <h2>分数:{count}</h2>
  16. <button onClick={()=>dispatch('add')}>加</button>
  17. <button onClick={()=>dispatch('sub')}>减</button>
  18. </>
  19. )
  20. }
  21. export default Demo
  • state 第一个参数 状态
  • action 控制业务逻辑的判断参数
  • useContext:可访问全局状态,避免一层层的传递状态
  • useReducer:通过action的传递,更新复杂逻辑的状态

颜色共享组件 color.js

  1. import React, { createContext,useReducer } from 'react';
  2. export const ColorContext = createContext({})
  3. export const UPDATE_COLOR = 'UPDATE_COLOR'
  4. const reducer = (state, action) => {
  5. switch(action.type){
  6. case UPDATE_COLOR:
  7. return action.color
  8. default:
  9. return state
  10. }
  11. }
  12. export const Color = props => {
  13. const [color, dispatch] = useReducer(reducer, 'blue')
  14. return (
  15. <ColorContext.Provider value = {{color,dispatch}}>
  16. {props.children}
  17. </ColorContext.Provider>
  18. )
  19. }
  • 用 {props.children} 来显示子组件
  • 将 color 和 dispatch 共享出去

showArea.js

  1. import React , { useContext } from 'react';
  2. import { ColorContext } from './color';
  3. function ShowArea(){
  4. const { color } = useContext(ColorContext)
  5. return (<div style={{ color:color }}>字体颜色为{ color }</div>)
  6. }
  7. export default ShowArea
  • 注意 引入 ColorContext 使用了大括号

Buttons.js

  1. import React , { useContext } from 'react';
  2. import { ColorContext, UPDATE_COLOR } from './color'
  3. function Buttons(){
  4. const { dispatch } = useContext(ColorContext)
  5. return (
  6. <div>
  7. <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"red"})}}>红色</button>
  8. <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"yellow"})}}>黄色</button>
  9. </div>
  10. )
  11. }
  12. export default Buttons

Demo.js

  1. import React, { useReducer } from 'react';
  2. import ShowArea from './ShowArea';
  3. import Buttons from './Buttons';
  4. import { Color } from './color'; //引入Color组件
  5. function Demo(){
  6. return (
  7. <>
  8. <Color>
  9. <ShowArea />
  10. <Buttons />
  11. </Color>
  12. </>
  13. )
  14. }
  15. export default Demo

用来解决使用 React hooks 产生的无用渲染的性能问题。

  1. import React , {useState,useMemo} from 'react';
  2. function Demo(){
  3. const [xiaohong , setXiaohong] = useState('小红待客状态')
  4. const [zhiling , setZhiling] = useState('志玲待客状态')
  5. return (
  6. <>
  7. <button onClick={()=>{setXiaohong(new Date().getTime())}}>小红</button>
  8. <button onClick={()=>{setZhiling(new Date().getTime()+',志玲向我们走来了')}}>志玲</button>
  9. <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>
  10. </>
  11. )
  12. }
  13. function ChildComponent({name,children}){
  14. function changeXiaohong(name){
  15. console.log('她来了,她来了。小红向我们走来了')
  16. return name+',小红向我们走来了'
  17. }
  18. const actionXiaohong = changeXiaohong(name)
  19. return (
  20. <>
  21. <div>{actionXiaohong}</div>
  22. <div>{children}</div>
  23. </>
  24. )
  25. }
  26. export default Demo

点击志玲按钮,小红对应的方法执行,虽然结果没变,但是每次都执行,损耗性能。

  1. function ChildComponent({name,children}){
  2. function changeXiaohong(name){
  3. console.log('她来了,她来了。小红向我们走来了')
  4. return name+',小红向我们走来了'
  5. }
  6. const actionXiaohong = useMemo(()=>changeXiaohong(name),[name])
  7. return (
  8. <>
  9. <div>{actionXiaohong}</div>
  10. <div>{children}</div>
  11. </>
  12. )
  13. }

第二个参数 [name] 匹配成功,才会执行。

  • 用来获取React JSX中的DOM元素
  • 用来保存变量
  1. import React, { useRef} from 'react';
  2. function Demo(){
  3. const inputEl = useRef(null)
  4. inputEl.current.value = "给 input value属性 赋值"
  5. return (
  6. <>
  7. <input ref={inputEl} type="text"/>
  8. </>
  9. )
  10. }
  11. export default Demo
  1. import React, { useRef, useState, useEffect } from 'react'
  2. function Demo(){
  3. const inputEl = useRef(null)
  4. inputEl.current.value="给 input value属性 赋值"
  5. const [text, setText] = useState('默认值')
  6. const textRef = useRef()
  7. useEffect(()=>{
  8. textRef.current = text
  9. })
  10. return (
  11. <>
  12. <input ref={inputEl} type="text"/>
  13. <input value={text} onChange={(e)=>{setText(e.target.value)}} />
  14. </>
  15. )
  16. }
  17. export default Demo
  • text 每次发生变化,将值保存到 useRef 中
  • 使用 useEffect 实现每次状态变化都进行变量重新赋值
  • 很少用到这个功能(保存变量)

编写自定义函数实现获取浏览器窗口

  1. import React, { useState, useEffect, useCallback } from 'react';
  2. function useWinSize(){
  3. const [ size , setSize] = useState({
  4. width:document.documentElement.clientWidth,
  5. height:document.documentElement.clientHeight
  6. })
  7. const onResize = useCallback(()=>{
  8. setSize({
  9. width: document.documentElement.clientWidth,
  10. height: document.documentElement.clientHeight
  11. })
  12. },[])
  13. useEffect(()=>{
  14. window.addEventListener('resize',onResize)
  15. return ()=>{
  16. window.removeEventListener('resize',onResize)
  17. }
  18. },[])
  19. return size;
  20. }
  21. function Demo(){
  22. const size = useWinSize()
  23. return (
  24. <div>页面Size:{size.width} x {size.height}</div>
  25. )
  26. }
  27. export default Demo
  • 命名要使用 use 开头以确认该函数是自定义 Hook 而不是组件
  • useCallback 用来缓存方法 ( useMemo 是为了缓存变量)
  • 第一次进入方法时用 useEffect 来注册 resize 监听事件
  • 防止一直监听所以在方法移除时,使用return的方式移除监听
  • 最后在 Demo 组件中使用

文章参考

  • 官方文档
  • 哔哩哔哩up主技术胖的 视频

版权声明:本文为guangzan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/guangzan/p/12210806.html