React18学习笔记(五) 【总结】常用的React Hooks函数,常用React-Redux Hooks函数和React中的组件通信

文章目录

      • [一.常用React Hooks函数](#一.常用React Hooks函数)
        • [1.useState - 状态管理](#1.useState - 状态管理)
        • [2.useEffect - 副作用处理](#2.useEffect - 副作用处理)
        • [3.useRef - 引用DOM或存储可变值](#3.useRef - 引用DOM或存储可变值)
        • [4.useMemo - 记忆化计算结果](#4.useMemo - 记忆化计算结果)
        • [5.useContext - 访问上下文](#5.useContext - 访问上下文)
        • [6.useCallback - 记忆化函数](#6.useCallback - 记忆化函数)
        • [7.自定义React Hooks函数](#7.自定义React Hooks函数)
      • [二.常用React-Redux Hooks函数](#二.常用React-Redux Hooks函数)
        • [1.useSelector - 访问Redux Store的状态](#1.useSelector - 访问Redux Store的状态)
        • [2.useDispatch - 分发Action](#2.useDispatch - 分发Action)
        • [3.useStore - 访问Store示例](#3.useStore - 访问Store示例)
      • 三.React中的组件通信

一.常用React Hooks函数

1.useState - 状态管理
  • 作用:用于在函数组件中添加状态管理,创建状态变量
  • 特点:状态变量只能由其状态更新函数来更新其值,状态更新时会触发组件重新渲染
  • 示例:
javascript 复制代码
import {useState} from "react"
const [isVisible,setIsVisible] = useState(false)
const handleClick=()=>{
	setIsVisible(!isVisible)
}
2.useEffect - 副作用处理

作用:处理组件中的副作用(数据获取,订阅,手动操作DOM等)

参数:副作用函数和依赖项

特点:在组件渲染后执行,通过依赖数组控制执行的时机

使用场景:API请求、事件监听、定时器、操作DOM

示例:

javascript 复制代码
	const [list,setList]=useState()
	useEffect(()=>{
		const getList=async()=>{
			const res=await axios.get(url)
			const list=res.data;
			setList(list)
		}
	},[list])
3.useRef - 引用DOM或存储可变值
  • 作用:创建可变的引用对象,其.current属性可保存值
  • 特点:更新.current属性不会触发组件重新渲染,常用于访问DOM节点
  • 常用场景:访问DOM元素、存定时器id,保存前一个状态值
  • 示例:获取input框的焦点
javascript 复制代码
  import { useState,useRef,useEffect } from 'react';
  const inputRef=useRef(null)
  const handleSubmit=()=>{
    console.log('发布评论')
    // 判断非空
    if(inputValue.trim()==='') return;
    // 发布评论
    const myComment={
      // rpid:`c${commentList.length+1}`,//替换成uuid
      rpid:uuidV4(),//当成一个可执行方法来使用,生成独一无二的id
      user:{...currentUser},
      content:inputValue,
      // ctime:new Date().toLocaleString('zh-CN').split(' ')[0].replace(/\//g, '-'),
      ctime:dayjs(new Date()).format('MM-DD hh:mm'),
      likes:0
    }
    // 提交新评论后:更新状态
    // 1.更新评论列表
    setCommentList([...commentList,myComment])
    // 2.清空input输入框
    setInputValue('')
    // 3.获取DOM元素,文本框重新获得焦点
    inputRef.current.focus();
  }
......
{/* 评论输入区 */}
<div className="comment-input-area">
  <input 
    type="text"
    placeholder="发个友善的评论吧..."
    value={inputValue}
    onChange={e=>setInputValue(e.target.value)}
    className="comment-input"
    ref={inputRef}
  />
  <button className='submit-btn' onClick={handleSubmit}>发布</button>
</div>
4.useMemo - 记忆化计算结果
  • 作用:记忆化计算结果,避免每次渲染都重新计算(类似Vue中的computed和getter)
  • 特点:依赖不变时返回缓存值,减少不必要的计算开销
  • 注意事项:不要用于有副作用的操作并确保计算函数是纯函数
  • 示例:
javascript 复制代码
  //pages/Month/index.js
  import { useState, useMemo, useEffect } from "react";
	......
  // 按月分组:消费数据分组处理
  const monthGroup = useMemo(() => {
    // return出去计算之后的值
    return _.groupBy(billList, (item) => dayjs(item.date).format("YYYY | MM"))
  }, [billList])
  console.log("消费数据(分组后):",monthGroup);
5.useContext - 访问上下文
  • 作用:访问React上下文中的值
  • 特点:避免props层层传递
  • 注意事项:组件会在上下文值变化时重新渲染,当使用多个上下文时嵌套顺序会影响值获取
  • 常用场景:主体切换、用户认证、多语言支持
  • 示例:
javascript 复制代码
// 1. 创建上下文
const ThemeContext = React.createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return <ThemedButton />;
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{
      background: theme === 'dark' ? '#333' : '#eee',
      color: theme === 'dark' ? '#fff' : '#000'
    }}>
      主题按钮
    </button>
  );
}
6.useCallback - 记忆化函数
  • 作用:返回记忆化的回调函数,避免每次渲染都创建新函数
  • 特点:依赖不变时防止相同的函数引用,优化子组件避免不必要的重新渲染
  • 注意事项:仅当函数的创建成本高或传递给子组件时使用
  • 常用场景:优化子组件props、事件处理函数
  • 示例:
javascript 复制代码
function Parent() {
  const [count, setCount] = useState(0);
  
  // 记忆化回调函数
  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);
  
  return (
    <div>
      <Child onIncrement={increment} />
      <p>计数: {count}</p>
    </div>
  );
}

// 使用React.memo优化子组件
const Child = React.memo(({ onIncrement }) => {
  console.log('子组件渲染');
  return <button onClick={onIncrement}>增加</button>;
});
7.自定义React Hooks函数
javascript 复制代码
const useToggle=()=>{
	const [show,setShow]=useState(true)
	const isToggle=()=>setShow(!show)
	return{
		show,
		isToggle
	}
}

const [show,isToggle]=useToggle();

<button onClick={isToggle}>
   {show ? "点击隐藏" : "点击显示"}
</button>

二.常用React-Redux Hooks函数

1.useSelector - 访问Redux Store的状态
  • 作用:从Redux store中提取和监听状态
  • 参数:一个选择器函数,接收整个state并返回需要的状态片段
  • 特点:当选择的值发生变化时,组件会重新渲染
  • 注意事项:选择器应简单高效,避免复杂计算,避免在 useSelector 中返回新的引用类型对象
  • 示例:引入后台消费数据
javascript 复制代码
/*省流:只看使用部分*/
//使用----组件内(pages/Month/index.js):
import { useSelector } from "react-redux";
const Month = () => {
  // 引入后台消费数据
  const billList = useSelector((state) => state.bill.billList)
  console.log("消费数据(原始):",billList)
}

//定义----store内(store/modules/billStore.js)
const billStore = createSlice({
  name: 'bill',
  initialState: {
    // 账单列表
    billList: [],
  },
  reducers: {
    // 设置账单列表
    setBillList(state, action) {
      state.billList = action.payload
    }
  }
})
const { setBillList } = billStore.actions

//导出/注册----入口文件内(store/index.js)
// 组合子模块,导出store实例
import billReducer from './modules/billStore.js'
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({
  reducer: {
    bill: billReducer// 这里的key要和子模块的name一致,即:name: 'bill'
  }
})
export default store
2.useDispatch - 分发Action
  • 功能:获取Redux storedispatch函数引用
  • 特点:返回的dispatch引用时稳定的,不会随着渲染改变
  • 最佳实践:把dispatch逻辑封装在回调函数中
  • 示例:
javascript 复制代码
//page/Layout/index.js----在useEffect中dispatch存于store中的Action异步方法
import { useDispatch } from 'react-redux'
import { useEffect } from "react";
const Layout = () => {
  const dispatch = useDispatch()
  useEffect(() => {// 组件挂载完成之后,执行异步请求消费数据列表(账单)
    dispatch(getBillList())
  }, [dispatch])
.....
}

//store/modules/billStore.js----store中的异步方法:
// 异步获取账单列表
const getBillList = () => {
  return async (dispatch) => {
    const res = await axios.get('http://localhost:8888/list')
    dispatch(setBillList(res.data))
  }
}
export { getBillList }
3.useStore - 访问Store示例
  • 功能:获取整个Redux store实例引用(不常用)
  • 使用场景:特定情况下须知直接访问整个store对象时,如手动订阅
  • 注意事项:大多数情况下应优先使用useSelector而非直接访问store
  • 示例:
javascript 复制代码
import { useStore } from 'react-redux';

function DebugComponent() {
  const store = useStore();
  
  // 获取当前状态快照
  const currentState = store.getState();
  
  // 监听状态变化
  useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      console.log('状态更新:', store.getState());
    });
    
    return unsubscribe;
  }, [store]);
  
  return <div>调试信息</div>;
}

三.React中的组件通信

1.父传子

父组件设置自定义属性,子组件函数中通过形参接收

javascript 复制代码
// 父组件
function Parent() {
  const [message, setMessage] = useState('Hello from Parent');
  
  return (
    <Child greeting={message} />
  );
}

// 子组件
function Child({ greeting }) {
  return <div>{greeting}</div>;
}
2.子传父

子组件设置事件的回调函数,父组件通过自定义事件名接收

javascript 复制代码
// 父组件
function Parent() {
  const handleChildEvent = (data) => {
    console.log('子组件传递的数据:', data);
  };
  
  return <Child onEvent={handleChildEvent} />;
}

// 子组件
function Child({ onEvent }) {
  const sendData = () => {
    onEvent({ value: '来自子组件的数据' });
  };
  
  return <button onClick={sendData}>发送数据</button>;
}
3.跨层级通信

使用Context API创建上下文

javascript 复制代码
// 创建上下文
const FamilyContext = React.createContext();

// 父组件
function Parent() {
  return (
    <FamilyContext.Provider value={{ surname: 'Smith' }}>
      <Child />
    </FamilyContext.Provider>
  );
}

// 子组件
function Child() {
  const family = useContext(FamilyContext);
  return <div>姓氏: {family.surname}</div>;
}
4.使用ref
javascript 复制代码
// 父组件
function Parent() {
  const childRef = useRef();
  
  const callChildMethod = () => {
    childRef.current.childMethod();
  };
  
  return (
    <>
      <Child ref={childRef} />
      <button onClick={callChildMethod}>调用子组件方法</button>
    </>
  );
}

// 子组件(使用 forwardRef)
const Child = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    childMethod: () => console.log('子组件方法被调用')
  }));
  
  return <div>子组件</div>;
});
相关推荐
ObjectX前端实验室4 小时前
React Fiber 双缓冲树机制深度解析
前端·react.js
ObjectX前端实验室6 小时前
【react18原理探究实践】分层解析React Fiber 核心工作流程
前端·react.js
ObjectX前端实验室7 小时前
【react18原理探究实践】scheduler原理之Task 完整生命周期解析
前端·react.js
ObjectX前端实验室7 小时前
【react18原理探究实践】调度器(Scheduler)原理深度解析
前端·react.js
FanetheDivine9 小时前
常见的AI对话场景和特殊情况
前端·react.js
ObjectX前端实验室20 小时前
【react18原理探究实践】异步可中断 & 时间分片
前端·react.js
gerrgwg1 天前
React Hooks入门
前端·javascript·react.js
ObjectX前端实验室1 天前
【react18原理探究实践】调度机制之注册任务
前端·react.js
ObjectX前端实验室1 天前
【React 原理探究实践】root.render 干了啥?——深入 render 函数
前端·react.js