React基础知识回顾详解
以下是React从前端面试基础到进阶的系统性学习内容,包含核心知识点和常见面试题解析:
一、React基础核心
-
JSX原理与本质
- JSX编译过程(Babel转换)
- 虚拟DOM工作原理
- 面试题:React为何使用className而不是class?
-
组件开发
- 类组件 vs 函数组件
- Props的不可变性原则
- State更新机制(批量更新)
// 函数组件示例 const Counter = () => { const [count, setCount] = useState(0); return <button onClick={() => setCount(c => c+1)}>{count}</button>; }
-
生命周期(类组件)
- 挂载阶段:constructor → render → componentDidMount
- 更新阶段:shouldComponentUpdate → render → componentDidUpdate
- 卸载阶段:componentWillUnmount
- 面试题:componentDidMount和useEffect(()=>{}, [])的区别?
二、Hooks深度解析
-
核心Hooks
- useState:状态管理
- useEffect:副作用管理
- useRef:DOM引用/持久化值
useEffect(() => { const timer = setInterval(() => { // 副作用逻辑 }, 1000); return () => clearInterval(timer); // 清理函数 }, []);
-
高级Hooks
- useCallback/useMemo:性能优化
- useContext:跨组件通信
- useReducer:复杂状态管理
- 自定义Hooks封装
const useFetch = (url) => { const [data, setData] = useState(null); useEffect(() => { fetch(url).then(res => res.json()).then(setData); }, [url]); return data; }
三、性能优化专题
-
渲染优化
- React.memo高阶组件
- PureComponent使用场景
- key属性的正确使用
const MemoList = React.memo(({ items }) => ( <div>{items.map(item => <div key={item.id}>{item.text}</div>)}</div> ));
-
计算优化
- useMemo缓存计算结果
- useCallback避免函数重建
const expensiveCalc = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]);
-
代码分割
- React.lazy + Suspense动态加载
- 面试题:如何实现路由懒加载?
四、状态管理进阶
-
Context API
- Provider/Consumer模式
- 性能陷阱与解决方案
const ThemeContext = createContext('light'); <ThemeContext.Provider value="dark"> <App /> </ThemeContext.Provider>
-
Redux核心
- Store/Action/Reducer工作流
- Redux Toolkit最佳实践
- 中间件原理(redux-thunk/redux-saga)
-
现代状态库
- Recoil原子化状态管理
- MobX响应式编程
- Zustand轻量级方案
五、React 18新特性
-
并发模式(Concurrent Mode)
- useTransition处理非阻塞更新
- useDeferredValue延迟渲染
const [isPending, startTransition] = useTransition(); startTransition(() => { // 非紧急状态更新 });
-
服务端渲染增强
- Streaming SSR流式渲染
- React Server Components
六、高频面试题精选
-
原理类
- React Diff算法如何工作?
- 虚拟DOM比真实DOM快吗?为什么?
- Fiber架构解决了什么问题?
-
实践类
- 如何避免组件重复渲染?
- 如何实现全局状态共享?
- 怎样处理表单复杂校验?
-
开放类
- 如果让你设计一个React框架,会考虑哪些方面?
- 如何实现组件级灰度发布?
七、学习路线建议
-
项目实践
- 实现一个完整后台管理系统
- 开发可视化图表组件库
- SSR电商网站(Next.js)
-
源码学习
- 调试React源码(从createElement开始)
- 实现简易版React(300行代码版)
-
持续关注
- React RFC提案(如useEvent)
- 生态库更新(TanStack Query、Remix)
掌握这些内容后,建议通过LeetCode React题库(如设计Hacker News客户端)和真实项目实践巩固知识,最终达到高级React开发者的水平。
总结需要解析的知识点:
函数组件的基本结构
useState钩子的使用和状态初始化
状态更新函数的使用(函数式更新)
事件处理与合成事件
JSX中的内联事件处理
函数组件与类组件的区别
Hooks的规则(如不能在条件或循环中调用)
性能优化的注意事项(如函数作为props时的重新渲染)
可能还需要解释为什么使用箭头函数定义组件,以及const和let在变量声明中的区别(虽然这里用的是const,因为组件不会被重新赋值)。
此外,这个例子中的组件没有接受props,所以可能需要提及props的使用,但当前例子中没有涉及,所以可能不需要展开。
以下是对之前提供的React计数器组件代码的逐层解析,涵盖核心知识点和面试常考点:
代码示例
const Counter = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c+1)}>{count}</button>;
}
一、组件定义解析
-
函数组件声明
const Counter = () => { ... }
- 使用箭头函数定义组件(也可用
function
声明) - 组件名称必须大写开头(React区分组件与原生标签的依据)
- 面试题:函数组件与类组件的本质区别是什么?
- 使用箭头函数定义组件(也可用
-
JSX返回值
return <button>...</button>;
- 必须返回单个根元素(React 16+支持Fragment空标签
<></>
) - JSX会被Babel编译为
React.createElement()
调用
- 必须返回单个根元素(React 16+支持Fragment空标签
二、Hooks核心机制
-
useState工作流程
const [count, setCount] = useState(0);
- 状态初始化:只在组件首次渲染时执行
- 闭包特性:state值在每次渲染中固定(闭包陷阱的产生原因)
- 更新机制:触发重新渲染但不会立即更新值
-
函数式更新
setCount(c => c + 1)
- 解决异步更新导致的状态不一致问题
- 推荐在连续操作中使用(如快速多次点击按钮)
- 面试题:
setCount(count+1)
连续调用3次会发生什么?
三、事件处理深度
-
合成事件系统
onClick={() => { ... }}
- React使用事件委托机制,所有事件绑定在root节点
- 自动处理事件池和浏览器兼容性
- 面试题:React事件与原生事件执行顺序是怎样的?
-
回调函数优化
// 当前写法:每次渲染创建新函数(可能引发子组件不必要渲染) <button onClick={() => setCount(...)}> // 优化方案:使用useCallback缓存函数 const handleClick = useCallback(() => setCount(...), []); <button onClick={handleClick}>
- 性能敏感场景需避免内联函数创建
- 面试题:如何避免因回调函数导致的子组件重复渲染?
四、渲染机制解析
-
渲染触发条件
- 父组件重新渲染
- 组件自身state变化
- 接收的props发生变化
-
渲染流程
五、常见问题解决方案
-
闭包陷阱
// 错误示例:异步操作中使用旧值 useEffect(() => { const timer = setInterval(() => { console.log(count); // 总是初始值 }, 1000); return () => clearInterval(timer); }, []); // 正确方案:使用ref保存最新值 const countRef = useRef(count); countRef.current = count;
-
批量更新
// React 17及之前版本:事件处理函数中的更新会被自动批处理 const handleClick = () => { setCount(c => c+1); setName('new'); // 只会触发一次渲染 } // React 18+:所有更新默认批处理
六、代码优化方向
-
组件拆分
const CountButton = ({ count, onClick }) => ( <button onClick={onClick}>{count}</button> )
- 提升可维护性
- 便于使用React.memo优化
-
状态管理升级
// 复杂场景使用useReducer const [state, dispatch] = useReducer(reducer, { count: 0 });
七、面试扩展问题
-
如果组件不更新可能是什么原因?
- 状态更新值相同(Object.is比较)
- 未正确传递依赖项(useEffect等Hook依赖数组)
- 父组件memo处理不当
-
如何实现跨组件状态共享?
- Context API
- 状态管理库(Redux等)
- 组合组件模式
通过这个简单的计数器组件,可以延伸出React的核心工作机制、性能优化策略以及常见开发陷阱的解决方案,这些正是前端面试的重点考察方向。建议在理解这些知识点后,尝试实现更复杂的场景(如异步计数器、多组件联动等)来加深理解。