本文详细介绍了React的基础概念和组件使用方法,并深入讲解了React大厂面试真题中的高频知识点,包括Hooks的使用、Context API的应用以及性能优化技巧。文章还提供了面试题解析与解答技巧,帮助读者更好地准备面试。
React 是一个由 Facebook 开发并维护的 JavaScript 库,用于构建用户界面,特别是单页面应用。它采用了一种声明式的方法,通过组件化的方式构建可重用的 UI 组件,使得开发者能够更容易地组织和管理代码。React 使用虚拟 DOM 来提高渲染效率,通过高效的 diff 算法计算出最小的数据变更,再将变更应用到实际的 DOM 上。
React 的核心概念包括组件、状态(State)、属性(Props)以及生命周期方法。React 应用中最基本的单元是组件,组件可以分为函数组件和类组件。函数组件是一个简单的 JavaScript 函数,而类组件则继承自 React 的 Component
类。状态和属性是组件中管理数据的核心,状态代表组件内部的数据,属性是组件接受外部数据的接口。生命周期方法涵盖了组件从创建到销毁的各个阶段,帮助开发者在这些阶段中执行特定的操作。
React 组件是构建应用的基本构建块。组件可以接受属性(Props)作为输入参数,并返回 JSX 作为输出结果。组件可以是函数组件或类组件。
函数组件:
函数组件接收一个 props
参数,返回 JSX 代码。函数组件通常用于表示没有状态的纯展示组件。
import React from 'react'; function Greeting(props) { return <h1>Hello, {props.name}</h1>; } export default Greeting;
类组件:
类组件继承自 React.Component
类,需要实现 render
方法,并且可以管理状态(State)。
import React from 'react'; class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } } export default Greeting;
状态(State)是组件内部的数据存储,而属性(Props)是组件从外部接收的数据。
状态(State):
状态是组件内部的数据,通常用于管理组件的内部状态。
import React, { Component } from 'react'; class Counter extends Component { constructor(props) { super(props); this.state = { count: 0, }; } incrementCount = () => { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.incrementCount}>Increment</button> </div> ); } } export default Counter;
属性(Props):
属性是组件接收外部数据的接口,通常用于传递数据和方法。
import React from 'react'; function Greeting(props) { return <h1>Hello, {props.name}</h1>; } export default function App() { return ( <div> <Greeting name="World" /> </div> ); }
React 组件的生命周期分为三个阶段:挂载阶段(Mounting)、更新阶段(Updating)、卸载阶段(Unmounting)。React 16.3 之后引入了生命周期钩子,如 componentDidMount
、componentDidUpdate
和 componentWillUnmount
,这些方法帮助开发者在组件生命周期的特定阶段执行特定的操作。最新的 React 18 版本中,生命周期钩子被修改,不再支持 componentWillMount
、componentWillReceiveProps
和 componentWillUpdate
。
生命周期钩子:
componentDidMount
:组件挂载后执行的操作。componentDidUpdate
:组件更新后执行的操作。componentWillUnmount
:组件卸载前执行的操作。import React, { Component } from 'react'; class MyComponent extends Component { componentDidMount() { console.log('Component did mount'); } componentDidUpdate(prevProps, prevState) { console.log('Component did update'); } componentWillUnmount() { console.log('Component will unmount'); } render() { return <div>Hello, World!</div>; } } export default MyComponent;
React Hooks 是 React 16.8 版本引入的一个新特性,允许在不编写类的情况下使用状态和其他 React 特性。常见的 Hooks 包括 useState
、useEffect
、useContext
、useReducer
和 useMemo
。
useState:
useState
用于在函数组件中添加状态。
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const incrementCount = () => { setCount(count + 1); }; return ( <div> <p>Count: {count}</p> <button onClick={incrementCount}>Increment</button> </div> ); } export default Counter;
useEffect:
useEffect
用于执行副作用操作,如网络请求、订阅、设置标题等。
import React, { useEffect } from 'react'; function App() { useEffect(() => { console.log('Component rendered'); }, []); return <div>Hello, World!</div>; } export default App;
React Context API 是一种在组件树中传递数据的机制,可以避免在每一个组件中传递 props,简化状态管理。
创建 Context:
创建一个 Context 对象,并提供一个默认值。
import React from 'react'; const MyContext = React.createContext('default value'); export default MyContext;
消费 Context:
使用 Context.Consumer
或 useContext
Hook 来消费 Context 的值。
import React, { useContext } from 'react'; import MyContext from './MyContext'; function MyComponent() { const contextValue = useContext(MyContext); return <div>{contextValue}</div>; } export default MyComponent;
提供 Context:
使用 Context.Provider
来提供 Context 的值,并传递给子组件。
import React, { useState } from 'react'; import MyContext from './MyContext'; import MyComponent from './MyComponent'; function App() { const [value] = useState('provided value'); return ( <MyContext.Provider value={value}> <MyComponent /> </MyContext.Provider> ); } export default App;
React 性能优化可以通过多种方式实现,包括使用 React.memo
、useMemo
和 useCallback
Hook,以及避免不必要的渲染。
使用 React.memo
:
React.memo
是一个高阶组件,用于组件的浅比较,避免不必要的渲染。
import React, { memo } from 'react'; const MyComponent = memo((props) => { return <div>{props.value}</div>; }); export default MyComponent;
使用 useMemo
:
useMemo
用于缓存计算昂贵的操作,避免不必要的计算。
import React, { useMemo } from 'react'; function MyComponent({ value }) { const expensive = useMemo(() => { console.log('Expensive calculation'); return value * value; }, [value]); return <div>{expensive}</div>; } export default MyComponent;
Redux 是一个用于管理应用状态的库,与 React 结合使用可以提高状态管理的效率。通过 Provider
和 connect
Hook,可以将 Redux 状态传递给 React 组件。
安装 Redux 和 React-Redux
npm install redux react-redux
创建 Redux Store
import { createStore } from 'redux'; const initialState = { count: 0, }; const reducer = (state = initialState, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; default: return state; } }; const store = createStore(reducer); export default store;
使用 Provider 和 connect
import React from 'react'; import { Provider, connect } from 'react-redux'; import store from './store'; function Counter({ count, dispatch }) { return ( <div> <p>Count: {count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button> </div> ); } const mapStateToProps = (state) => ({ count: state.count, }); const ConnectedCounter = connect(mapStateToProps)(Counter); function App() { return ( <Provider store={store}> <ConnectedCounter /> </Provider> ); } export default App;
面试题中常见的知识点包括 React 的基础概念、组件的使用、状态和属性的管理、生命周期方法、Hooks 的使用、Context API 的应用、React 与 Redux 的集成等。
基础概念
组件
状态和属性
state
和 props
?生命周期方法
面试中可能会遇到一些设计陷阱的问题,例如:
陷阱问题
React.memo
和 React.PureComponent
的区别。useCallback
和 useMemo
的区别。面试前要做好充分的准备,包括复习基础概念、熟悉 React 生态系统、练习编写代码和准备常见的面试题。保持冷静和自信,不要过于紧张,遇到不会的问题可以坦诚地说自己不了解。
准备
心态调整
构建一个简单的待办事项列表应用,包括添加、删除和编辑待办事项的功能。
安装依赖
npm install react react-dom
创建项目结构
mkdir todo-app cd todo-app touch index.js App.js style.css
App.js
import React, { useState } from 'react'; function App() { const [todos, setTodos] = useState([]); const [input, setInput] = useState(''); const addTodo = () => { if (input.trim() === '') return; setTodos([...todos, { text: input }]); setInput(''); }; const removeTodo = (index) => { const newTodos = todos.filter((_, i) => i !== index); setTodos(newTodos); }; return ( <div> <input type="text" value={input} onChange={(e) => setInput(e.target.value)} /> <button onClick={addTodo}>Add Todo</button> <ul> {todos.map((todo, index) => ( <li key={index}> {todo.text} <button onClick={() => removeTodo(index)}>Remove</button> </li> ))} </ul> </div> ); } export default App;
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root'));
集成 React Router,实现多页面应用,包括用户列表和用户详情页。
安装依赖
npm install react-router-dom
App.js
import React from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import UserList from './UserList'; import UserDetails from './UserDetails'; function App() { return ( <Router> <Switch> <Route exact path="/" component={UserList} /> <Route path="/user/:id" component={UserDetails} /> </Switch> </Router> ); } export default App;
UserList.js
import React from 'react'; function UserList() { const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]; return ( <ul> {users.map((user) => ( <li key={user.id}> <a href={`/${user.id}`}>{user.name}</a> </li> ))} </ul> ); } export default UserList;
UserDetails.js
import React from 'react'; import { useParams } from 'react-router-dom'; function UserDetails() { const { id } = useParams(); const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]; const user = users.find((user) => user.id === parseInt(id)); if (!user) return null; return <h2>{user.name}</h2>; } export default UserDetails;
使用 Context API 来管理全局状态,例如用户登录状态。
创建 Context
import React from 'react'; const AuthContext = React.createContext(null); export default AuthContext;
Provider 组件
import React, { useState } from 'react'; import AuthContext from './AuthContext'; function AuthProvider({ children }) { const [isAuthenticated, setIsAuthenticated] = useState(false); const login = () => { setIsAuthenticated(true); }; const logout = () => { setIsAuthenticated(false); }; return ( <AuthContext.Provider value={{ isAuthenticated, login, logout }} children={children} /> ); } export default AuthProvider;
消费 Context
import React, { useContext } from 'react'; import AuthContext from './AuthContext'; function AuthButton() { const { isAuthenticated, login, logout } = useContext(AuthContext); return ( <div> {isAuthenticated ? ( <button onClick={logout}>Logout</button> ) : ( <button onClick={login}>Login</button> )} </div> ); } export default AuthButton;
React Fiber 是 React 16 引入的一个新架构,旨在改善渲染性能、支持并发任务和实现优先级调度。Fiber 架构将渲染过程分为多个小任务,每个任务可以被中断和重新安排,从而提高了应用的响应性和流畅度。
Fiber 架构的关键点
React 虚拟 DOM 是 React 应用的核心概念之一,用于提高渲染效率。虚拟 DOM 是一个轻量级的 JavaScript 对象,用于表示实际的 DOM 元素。React 通过比较虚拟 DOM 和实际 DOM 的差异,只更新实际 DOM 中需要修改的部分,从而减少了 DOM 操作的数量,提高了应用的性能。
虚拟 DOM 的工作流程
高阶组件是 React 的一种复用组件逻辑的高级模式,可以包装其他组件并传递一些新的属性或方法。自定义 Hook 是一种实现可重用逻辑的方法,允许在不编写类的情况下使用状态和其他 React 特性。
高阶组件
高阶组件是一个函数,接受一个组件作为参数,并返回一个新的组件。
import React from 'react'; function withLogging(WrappedComponent) { return class extends React.Component { componentDidMount() { console.log('Component mounted'); } render() { return <WrappedComponent {...this.props} />; } }; } const EnhancedComponent = withLogging(MyComponent);
自定义 Hook
自定义 Hook 是一个函数,可以使用 React 的 Hook API,如 useState
、useEffect
等。
import React, { useState, useEffect } from 'react'; function useCounter(initialCount = 0) { const [count, setCount] = useState(initialCount); const increment = () => { setCount(count + 1); }; return [count, increment]; } function Counter() { const [count, increment] = useCounter(0); return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> </div> ); } export default Counter;
面试后应该总结面试的过程和结果,反思自己在面试中的表现,找出不足并改进。可以通过回顾面试问题、评估自己的答案、分析面试官的反馈来提高自己。
总结
改进
技术栈的提升是一个持续的过程,需要不断学习新的技术和框架,保持技术的更新。可以通过参加在线课程、阅读技术文档、参与开源项目等方式来提高自己的技术水平。
在线课程
技术文档
技术栈的提升不仅仅是学习新的技术,还需要通过实际项目来应用和巩固所学的知识。可以通过以下几个方面来持续提升自己的技术栈:
实践
社区参与
技术分享
通过这些方法,不断学习和成长,你的技术栈将会得到持续的提升。