React 概念:深入指南

React 是一个强大的 JavaScript 库,用于构建交互式用户界面。下面我们将详细介绍每一个主要的 React 概念,并提供详细的代码示例,逐步进行讲解。

1. 组件

  • 定义:组件是任何 React 应用的构建块。它们是可复用的 UI 单元,封装了逻辑、标记和样式。
  • 类型:主要有两种类型:
    • 函数组件:使用 JavaScript 函数创建的组件。从 React 16.8 开始,可以通过 hooks 使用状态和其他 React 特性。
    • 类组件:JavaScript 类,继承自 React.Component。这些组件在 hooks 出现之前更为常用。
  • 为何使用组件:组件帮助将 UI 分解为更小、更易于管理的部分,使代码更具复用性、更易于维护和测试。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 函数组件示例
    function Greeting(props) {
    return <h1>Hello, {props.name}!</h1>;
    }

    // 类组件示例
    class Welcome extends React.Component {
    render() {
    return <h1>Welcome, {this.props.name}!</h1>;
    }
    }

2. JSX (JavaScript XML)

  • 定义:JSX 是一种语法扩展,看起来像是 HTML 和 JavaScript 的混合。它允许开发者在 JavaScript 中直接编写 UI 模板。
  • 为何使用 JSX:将标记和逻辑结合,使代码更易读。JSX 在底层被编译为 React.createElement() 函数调用。
  • 代码示例
    1
    2
    3
    const element = <h1>Hello, world!</h1>;
    // 编译为:
    const element = React.createElement('h1', null, 'Hello, world!');

3. Props (属性)

  • 定义:Props 是组件的输入,用于在组件之间传递数据。
  • 不可变性:Props 是只读的。它们允许组件接收动态数据,并由父组件传递给子组件。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    function Button(props) {
    return <button onClick={props.onClick}>{props.label}</button>;
    }

    function App() {
    return <Button label="Click me" onClick={() => alert('Button clicked!')} />;
    }

4. State (状态)

  • 定义:State 是一个内置的 React 对象,用于存储组件生命周期中可能变化的数据。
  • 与 Props 的区别:与 Props 不同,State 是可变的,并在组件内部管理。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import React, { useState } from 'react';

    function Counter() {
    const [count, setCount] = useState(0);
    return (
    <div>
    <p>Count: {count}</p>
    <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
    );
    }

5. 生命周期方法 (在类组件中)

  • 定义:生命周期方法是在组件生命周期的特定时间运行的方法,比如组件挂载、更新或卸载时。
  • 关键方法
    • componentDidMount:在组件添加到 DOM 后立即调用。
    • componentDidUpdate:在组件更新后运行,适合在状态或 props 更改后执行操作。
    • componentWillUnmount:在组件从 DOM 中移除之前调用。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Timer extends React.Component {
    componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000);
    }

    componentWillUnmount() {
    clearInterval(this.timerID);
    }

    tick() {
    console.log('Tick');
    }

    render() {
    return <div>Timer is running...</div>;
    }
    }

6. Hooks

  • 定义:Hooks 是一些函数,允许在函数组件中使用 React 的状态和其他特性。
  • 常用 Hooks
    • useState:为函数组件添加状态。
    • useEffect:用于执行副作用操作,比如数据获取和订阅。
    • useContext:无需包装元素即可访问 React 上下文。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React, { useEffect } from 'react';

    function DataFetcher() {
    useEffect(() => {
    // 模拟数据获取
    console.log('Fetching data...');
    }, []); // 空数组表示只在初次渲染时运行

    return <div>Data fetched.</div>;
    }

7. Context API

  • 定义:Context API 允许组件共享值(如主题或用户数据),而无需通过每一层组件逐层传递 props。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import React, { createContext, useContext } from 'react';

    const ThemeContext = createContext('light');

    function ThemedComponent() {
    const theme = useContext(ThemeContext);
    return <div>The current theme is {theme}</div>;
    }

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

8. React Router

  • 定义:React Router 是一个用于路由的库,帮助在不同组件之间导航而无需页面重新加载。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

    function Home() {
    return <h2>Home Page</h2>;
    }

    function About() {
    return <h2>About Page</h2>;
    }

    function App() {
    return (
    <Router>
    <nav>
    <Link to="/">Home</Link>
    <Link to="/about">About</Link>
    </nav>
    <Switch>
    <Route exact path="/" component={Home} />
    <Route path="/about" component={About} />
    </Switch>
    </Router>
    );
    }

9. 状态管理

  • 局部状态:由各个组件内部使用的状态,通过 useStatesetState 来管理。
  • 全局状态:通过 ReduxRecoilContext API 等工具管理,以在多个组件之间共享状态。
  • Redux 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import { createStore } from 'redux';
    import { Provider, useDispatch, useSelector } from 'react-redux';

    const initialState = { count: 0 };

    function reducer(state = initialState, action) {
    switch (action.type) {
    case 'INCREMENT':
    return { count: state.count + 1 };
    default:
    return state;
    }
    }

    const store = createStore(reducer);

    function Counter() {
    const count = useSelector((state) => state.count);
    const dispatch = useDispatch();
    return (
    <div>
    <p>Count: {count}</p>
    <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
    </div>
    );
    }

    function App() {
    return (
    <Provider store={store}>
    <Counter />
    </Provider>
    );
    }

10. 协调 (Reconciliation)

  • 定义:React 在数据更改时,用于高效更新 UI 的过程。
  • 虚拟 DOM:React 使用实际 DOM 的轻量级表示形式,使更改和更新更快。
  • 代码示例
    1
    // React 内部会对比虚拟 DOM,以找到需要更新的部分,并只对这些部分进行更新。

11. Keys

  • 定义:为动态生成的元素(尤其是列表)提供唯一标识符。
  • 为何使用 Keys:它们帮助 React 识别哪些项已更改、添加或删除,从而优化重新渲染。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function ItemList({ items }) {
    return (
    <ul>
    {items.map((item) => (
    <li key={item.id}>{item.name}</li>
    ))}
    </ul>
    );
    }

12. 高阶组件 (HOCs)

  • 定义:一个接受组件并返回一个新增强组件的函数。
  • 为何使用 HOCs:它们允许在多个组件间复用逻辑,而无需重复代码。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function withLogging(WrappedComponent) {
    return function EnhancedComponent(props) {
    console.log('Rendering component with props:', props);
    return <WrappedComponent {...props} />;
    };
    }

    function SimpleComponent({ message }) {
    return <div>{message}</div>;
    }

    const EnhancedComponent = withLogging(SimpleComponent);

13. 错误边界 (Error Boundaries)

  • 定义:用于捕获子组件树中任何 JavaScript 错误的组件。
  • 使用场景:防止当某部分 UI 出错时导致整个应用崩溃,并提供备用 UI。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    class ErrorBoundary extends React.Component {
    constructor(props) {
    super(props);
    this.state = { hasError: false };
    }

    static getDerivedStateFromError(error) {
    return { hasError: true };
    }

    componentDidCatch(error, info) {
    console.log('Error caught:', error, info);
    }

    render() {
    if (this.state.hasError) {
    return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
    }
    }

    function BuggyComponent() {
    throw new Error('I crashed!');
    }

    function App() {
    return (
    <ErrorBoundary>
    <BuggyComponent />
    </ErrorBoundary>
    );
    }

14. 受控与非受控组件

  • 受控组件:由 React 通过状态控制其值的输入元素。
  • 非受控组件:数据由 DOM 本身处理,使用 ref 获取其值。
  • 为何重要:受控组件提供了更多的控制,易于验证,而非受控组件在某些情况下更为简单。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import React, { useRef, useState } from 'react';

    function ControlledInput() {
    const [value, setValue] = useState('');
    return (
    <input
    type="text"
    value={value}
    onChange={(e) => setValue(e.target.value)}
    />
    );
    }

    function UncontrolledInput() {
    const inputRef = useRef(null);
    const handleSubmit = () => {
    alert(`Input value: ${inputRef.current.value}`);
    };
    return (
    <div>
    <input type="text" ref={inputRef} />
    <button onClick={handleSubmit}>Submit</button>
    </div>
    );
    }

15. Fragments (片段)

  • 定义:Fragments 允许将多个子元素分组,而不向 DOM 添加额外的节点。
  • 使用场景:避免添加不必要的包装 div,从而生成更简洁的标记。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import React from 'react';

    function Table() {
    return (
    <table>
    <tbody>
    <tr>
    <React.Fragment>
    <td>Column 1</td>
    <td>Column 2</td>
    </React.Fragment>
    </tr>
    </tbody>
    </table>
    );
    }

16. Portals (传送门)

  • 定义:Portals 允许将子元素渲染到 DOM 树中的不同部分,脱离主组件层次结构。
  • 使用场景:适用于模态框、工具提示或其他需要在父组件之外的 UI。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import React from 'react';
    import ReactDOM from 'react-dom';

    function Modal({ children }) {
    return ReactDOM.createPortal(
    <div className="modal">
    {children}
    </div>,
    document.getElementById('modal-root')
    );
    }

    function App() {
    return (
    <div>
    <h1>Main Application</h1>
    <Modal>
    <p>This is a modal content!</p>
    </Modal>
    </div>
    );
    }

17. Memoization 和 React.memo

  • 定义React.memo 是一个高阶组件,用于缓存结果,防止不必要的重新渲染。
  • 为何使用缓存:提升性能,尤其是对重新渲染开销较大的组件。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import React from 'react';

    const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
    console.log('Rendering ExpensiveComponent');
    return <div>{data}</div>;
    });

    function App() {
    const [count, setCount] = useState(0);
    return (
    <div>
    <button onClick={() => setCount(count + 1)}>Increment</button>
    <ExpensiveComponent data="This is expensive!" />
    </div>
    );
    }

18. 严格模式 (Strict Mode)

  • 定义:一种仅在开发环境中使用的工具,用于帮助识别潜在问题,启用额外的检查。
  • 如何使用:用 <React.StrictMode> 包裹应用或其部分。
  • 好处:检测已弃用的特性、意外的副作用,帮助编写更好的代码。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import React from 'react';
    import ReactDOM from 'react-dom';

    ReactDOM.render(
    <React.StrictMode>
    <App />
    </React.StrictMode>,
    document.getElementById('root')
    );

19. 服务器端渲染 (SSR)

  • 定义:在服务器上渲染组件并将 HTML 发送给客户端。
  • 工具:像 Next.js 这样的流行框架支持 SSR。
  • 好处:更快的初始页面加载、更好的 SEO、在低网络环境下性能更好。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 在 Next.js 中实现 SSR
    import React from 'react';

    function Home({ data }) {
    return <div>{data}</div>;
    }

    export async function getServerSideProps() {
    const res = await fetch('https://api.example.com/data');
    const data = await res.json();
    return {
    props: { data },
    };
    }

    export default Home;

20. 代码分割和懒加载

  • 代码分割:将应用拆分为较小的包,以减少初始加载时间。
  • 懒加载:仅加载当前视图所需的代码。
  • 工具:React 的 React.lazy()Suspense 帮助实现懒加载。
  • 代码示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import React, { Suspense } from 'react';

    const OtherComponent = React.lazy(() => import('./OtherComponent'));

    function App() {
    return (
    <div>
    <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
    </Suspense>
    </div>
    );
    }

总结

理解这些核心概念可以帮助你使用 React 开发高效、强大和可维护的应用程序。每个概念相互协作,增强开发者构建现代用户界面和 Web 应用的方式。


https://withesse.co/post/react/
Author
zt
Posted on
May 27, 2025
Licensed under