目录一、React表单控制1. 受控绑定2. 非受控绑定二、组件通信1. 父子通信-父传子2. 父子通信-子传父3. 兄弟组件通信4. 跨层组件通信三、React副作用管理-useEffect1. 概念理解2. 基础使用3. useEffect依赖说明4. 清除副作用四、自定义Hook实现五、React Hooks使用规则六、实战案例-评论系统功能需求​编辑实现思路核心代码七、总结React开发核心概念解析本文系统讲解了React开发中的关键知识点包括表单控制的两种方式受控绑定和非受控绑定及其应用场景组件通信的多种实现方法父子、兄弟、跨层通信useEffect副作用管理的使用技巧和最佳实践自定义Hook的封装思路与优势以及Hooks的使用规则。通过评论系统实战案例展示了如何综合运用这些技术构建完整功能。掌握这些核心概念将帮助开发者构建更健壮、可维护的React应用。一、React表单控制在React中表单控制是一个重要的概念主要有两种方式受控绑定和非受控绑定。1. 受控绑定概念使用React组件的状态useState控制表单的状态。实现代码function App(){ const [value, setValue] useState() return ( input typetext value{value} onChange{e setValue(e.target.value)} / ) }优缺点优点数据与UI同步便于表单验证和处理缺点每次输入都会触发重新渲染可能影响性能2. 非受控绑定概念通过获取DOM的方式获取表单的输入数据。实现代码function App(){ const inputRef useRef(null) ​ const onChange (){ console.log(inputRef.current.value) } return ( input typetext ref{inputRef} onChange{onChange} / ) }使用场景简单表单不需要实时验证文件上传等特殊输入性能要求较高的场景二、组件通信组件通信是React中非常重要的概念根据组件嵌套关系的不同有不同的通信手段和方法。1. 父子通信-父传子实现步骤父组件传递数据 - 在子组件标签上绑定属性子组件接收数据 - 子组件通过props参数接收数据实现代码function Son(props){ return div{ props.name }/div } ​ function App(){ const name this is app name return ( div Son name{name}/ /div ) }props说明props可以传递任意的合法数据比如数字、字符串、布尔值、数组、对象、函数、JSXprops是只读对象子组件只能读取props中的数据不能直接进行修改特殊的prop-children当我们把内容嵌套在组件的标签内部时组件会自动在名为children的prop属性中接收该内容。2. 父子通信-子传父核心思路在子组件中调用父组件中的函数并传递参数。实现代码function Son({ onGetMsg }){ const sonMsg this is son msg return ( div {/* 在子组件中执行父组件传递过来的函数 */} button onClick{()onGetMsg(sonMsg)}send/button /div ) } ​ function App(){ const getMsg (msg)console.log(msg) return ( div {/* 传递父组件中的函数到子组件 */} Son onGetMsg{ getMsg }/ /div ) }3. 兄弟组件通信实现思路借助状态提升机制通过共同的父组件进行兄弟之间的数据传递。A组件先通过子传父的方式把数据传递给父组件AppApp拿到数据之后通过父传子的方式再传递给B组件实现代码import { useState } from react ​ function A ({ onGetAName }) { // Son组件中的数据 const name this is A name return ( div this is A compnent, button onClick{() onGetAName(name)}send/button /div ) } ​ function B ({ name }) { return ( div this is B compnent, {name} /div ) } ​ function App () { const [name, setName] useState() const getAName (name) { setName(name) } return ( div this is App A onGetAName{getAName} / B name{name} / /div ) } ​ export default App4. 跨层组件通信实现步骤使用createContext方法创建一个上下文对象Ctx在顶层组件App中通过Ctx.Provider组件提供数据在底层组件B中通过useContext钩子函数获取消费数据实现代码// App - A - B ​ import { createContext, useContext } from react ​ // 1. createContext方法创建一个上下文对象 ​ const MsgContext createContext() ​ function A () { return ( div this is A component B / /div ) } ​ function B () { // 3. 在底层组件 通过useContext钩子函数使用数据 const msg useContext(MsgContext) return ( div this is B compnent,{msg} /div ) } ​ function App () { const msg this is app msg return ( div {/* 2. 在顶层组件 通过Provider组件提供数据 */} MsgContext.Provider value{msg} this is App A / /MsgContext.Provider /div ) } ​ export default App三、React副作用管理-useEffect1. 概念理解useEffect是一个React Hook函数用于在React组件中创建不是由事件引起而是由渲染本身引起的操作副作用比如发送AJAX请求更改DOM等等。2. 基础使用需求在组件渲染完毕之后立刻从服务端获取平道列表数据并显示到页面中。说明参数1是一个函数可以把它叫做副作用函数在函数内部可以放置要执行的操作参数2是一个数组可选参在数组里放置依赖项不同依赖项会影响第一个参数函数的执行当是一个空数组的时候副作用函数只会在组件渲染完毕之后执行一次3. useEffect依赖说明useEffect副作用函数的执行时机存在多种情况根据传入依赖项的不同会有不同的执行表现依赖项副作用函数的执行时机没有依赖项组件初始渲染 组件更新时执行空数组依赖只在初始渲染时执行一次添加特定依赖项组件初始渲染 依赖项变化时执行4. 清除副作用概念在useEffect中编写的由渲染本身引起的对接组件外部的操作社区也经常把它叫做副作用操作比如在useEffect中开启了一个定时器我们想在组件卸载时把这个定时器再清理掉这个过程就是清理副作用。实现代码import { useEffect, useState } from react ​ function Son () { // 1. 渲染时开启一个定时器 useEffect(() { const timer setInterval(() { console.log(定时器执行中...) }, 1000) ​ return () { // 清除副作用(组件卸载时) clearInterval(timer) } }, []) return divthis is son/div } ​ function App () { // 通过条件渲染模拟组件卸载 const [show, setShow] useState(true) return ( div {show Son /} button onClick{() setShow(false)}卸载Son组件/button /div ) } ​ export default App最佳实践对于需要清理的副作用如定时器、事件监听器、网络请求等一定要在返回函数中进行清理依赖项数组要正确设置避免不必要的重复执行避免在useEffect中修改依赖项防止无限循环四、自定义Hook实现概念自定义Hook是以use打头的函数通过自定义Hook函数可以用来实现逻辑的封装和复用。实现代码// 封装自定义Hook ​ // 问题: 布尔切换的逻辑 当前组件耦合在一起的 不方便复用 ​ // 解决思路: 自定义hook ​ import { useState } from react ​ function useToggle () { // 可复用的逻辑代码 const [value, setValue] useState(true) ​ const toggle () setValue(!value) ​ // 哪些状态和回调函数需要在其他组件中使用 return return { value, toggle } } ​ // 封装自定义hook通用思路 ​ // 1. 声明一个以use打头的函数 // 2. 在函数体内封装可复用的逻辑只要是可复用的逻辑 // 3. 把组件中用到的状态或者回调return出去以对象或者数组 // 4. 在哪个组件中要用到这个逻辑就执行这个函数解构出来状态和回调进行使用 ​ function App () { const { value, toggle } useToggle() return ( div {value divthis is div/div} button onClick{toggle}toggle/button /div ) } ​ export default App自定义Hook的优势逻辑复用将组件中重复的逻辑提取到自定义Hook中代码整洁使组件代码更加简洁关注点分离可维护性便于测试和维护五、React Hooks使用规则只能在组件中或者其他自定义Hook函数中调用只能在组件的顶层调用不能嵌套在if、for、其它的函数中违反规则的后果React依赖Hooks的调用顺序来正确管理状态违反规则可能导致状态混乱或组件行为异常六、实战案例-评论系统功能需求手机输入框评论内容并发布评论id处理和时间处理使用请求接口的方式获取评论列表并渲染使用自定义Hook函数封装数据请求的逻辑把评论中的每一项抽象成一个独立的组件实现渲染实现思路状态管理使用useState管理评论列表和输入内容数据获取使用useEffect和自定义Hook获取评论数据组件拆分将评论项拆分为独立组件表单处理使用受控组件处理评论输入ID和时间使用UUID生成唯一ID使用day.js处理时间核心代码// 自定义Hook - useComments import { useState, useEffect } from react; ​ function useComments() { const [comments, setComments] useState([]); const [loading, setLoading] useState(false); const [error, setError] useState(null); ​ useEffect(() { const fetchComments async () { setLoading(true); try { // 实际项目中替换为真实API // const response await fetch(http://api.example.com/comments); // const data await response.json(); // 模拟数据 const data [ { id: 1, content: 这是一条评论, author: 用户1, time: new Date().toISOString() } ]; setComments(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; ​ fetchComments(); }, []); ​ const addComment (content) { const newComment { id: Date.now().toString(), content, author: 当前用户, time: new Date().toISOString() }; setComments([...comments, newComment]); }; ​ return { comments, loading, error, addComment }; } ​ export default useComments;七、总结通过本文的学习我们掌握了React中的几个核心概念表单控制了解了受控绑定和非受控绑定的区别及使用场景组件通信掌握了父子通信、兄弟通信和跨层通信的实现方法副作用管理学会了使用useEffect处理副作用并了解了依赖项的重要性自定义Hook理解了如何封装可复用的逻辑Hooks规则知道了使用Hooks的注意事项这些知识是React开发中的基础掌握它们将有助于我们构建更加健壮、可维护的React应用。在实际开发中我们需要根据具体场景选择合适的技术方案灵活运用这些概念。