React 函数组件

76 阅读15分钟

深入理解 React 函数组件对于构建现代 Web 应用至关重要。随着 React Hooks 的引入,函数组件不仅具备了类组件的所有功能,还带来了更简洁、可复用和易于测试的代码结构。对于熟悉 Vue 3 的开发者而言,React 函数组件的概念与 Vue 3 的组合式 API 有许多相似之处,但也存在一些独特的特性和实现方式。本文将全面解析 React 函数组件,从基础概念到高级主题,帮助你深入理解并高效使用它们。


目录

  1. 什么是 React 函数组件?
  2. 函数组件与类组件的对比
  3. React Hooks 概述
  1. 组件生命周期管理
  1. 组件组合与复用
  1. 性能优化
  1. TypeScript 与函数组件
  2. 与 Vue 3 组合式 API 的对比
  3. 最佳实践
  4. 高级主题
  1. 总结

1. 什么是 React 函数组件?

函数组件(Functional Components)是使用 JavaScript 函数定义的 React 组件。与传统的类组件相比,函数组件更简洁、易于理解,并且在引入 Hooks 之前,主要用于展示性组件(无状态)。自从 Hooks 引入后,函数组件可以管理状态、处理副作用等,几乎具备了类组件的所有功能。

基本示例:

import React from 'react';

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

export default Greeting;

箭头函数组件:

const Greeting = ({ name }) => <h1>Hello, {name}!</h1>;

export default Greeting;

2. 函数组件与类组件的对比

2.1 语法和结构

类组件:

import React, { Component } from 'react';

class Greeting extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <h1>Hello, {this.props.name}!</h1>

        <p>Count: {this.state.count}</p>

        <button onClick={this.handleClick}>Increase</button>

      </div>

    );
  }
}

export default Greeting;

函数组件:

import React, { useState } from 'react';

function Greeting({ name }) {
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(count + 1);

  return (
    <div>
      <h1>Hello, {name}!</h1>

      <p>Count: {count}</p>

      <button onClick={handleClick}>Increase</button>

    </div>

  );
}

export default Greeting;

2.2 状态管理

  • 类组件使用 this.statethis.setState 来管理状态。
  • 函数组件使用 Hooks(如 useState)来管理状态。

2.3 生命周期方法

  • 类组件通过生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)管理副作用和生命周期。
  • 函数组件使用 useEffect Hook 来管理副作用,模拟生命周期方法。

2.4 绑定方法

  • 类组件需要在构造函数中绑定事件处理方法,或者使用类字段语法。
  • 函数组件不需要绑定 this,事件处理方法可以直接在函数内部定义。

2.5 简洁性和可读性

  • 函数组件通常比类组件更简洁,代码更易读和维护。
  • 函数组件支持更好的代码复用和逻辑组合,通过自定义 Hooks 实现。

3. React Hooks 概述

Hooks 是 React 16.8 引入的功能,允许在函数组件中使用状态和其他 React 特性。Hooks 提供了一种无需编写类即可使用状态和生命周期功能的方式,大大提升了函数组件的能力和灵活性。

3.1 useState

useState Hook 允许在函数组件中添加状态。它返回一个状态变量和一个更新该状态的函数。

示例:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 初始化状态为 0

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  return (
    <div>
      <p>当前计数: {count}</p>

      <button onClick={increment}>增加</button>

      <button onClick={decrement}>减少</button>

    </div>

  );
}

export default Counter;

对比 Vue 3:

在 Vue 3 中,使用 refreactive 来管理状态:

<template>
  <div>
    <p>当前计数: {{ count }}</p>

    <button @click="increment">增加</button>

    <button @click="decrement">减少</button>

  </div>

</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);

const increment = () => count.value++;
const decrement = () => count.value--;
</script>

3.2 useEffect

useEffect Hook 用于在函数组件中处理副作用,如数据获取、订阅、手动操作 DOM 等。它可以模拟类组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount

基本用法:

import React, { useState, useEffect } from 'react';

function FetchData({ url }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 类似于 componentDidMount 和 componentDidUpdate
    fetch(url)
      .then(response => response.json())
      .then(data => setData(data));
  }, [url]); // 依赖项数组

  if (!data) return <p>Loading...</p>;

  return <div>{JSON.stringify(data)}</div>;
}

export default FetchData;

清理副作用:

useEffect(() => {
  const timer = setInterval(() => {
    console.log('Tick');
  }, 1000);

  return () => clearInterval(timer); // 类似于 componentWillUnmount
}, []);

3.3 useContext

useContext Hook 允许在函数组件中消费上下文(Context)。它简化了组件之间共享数据的方式,无需使用嵌套的 Context.Consumer

示例:

import React, { createContext, useContext } from 'react';

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>按钮</button>;
}

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

  );
}

export default App;

3.4 useReducer

useReducer Hook 适用于处理复杂的状态逻辑,类似于 Redux 中的 reducer 概念。它提供了一种更结构化的方式来管理状态更新。

示例:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>当前计数: {state.count}</p>

      <button onClick={() => dispatch({ type: 'increment' })}>增加</button>

      <button onClick={() => dispatch({ type: 'decrement' })}>减少</button>

    </div>

  );
}

export default Counter;

3.5 useRef

useRef Hook 用于在函数组件中创建一个可变的引用,该引用在组件的整个生命周期内保持不变。常用于访问 DOM 元素或存储任何可变值。

示例:

import React, { useRef } from 'react';

function TextInput() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>聚焦输入框</button>

    </div>

  );
}

export default TextInput;

3.6 自定义 Hooks

自定义 Hooks 允许你将组件逻辑提取到可重用的函数中。它们遵循命名约定,以 use 开头,利用现有的 Hooks 构建更复杂的功能。

示例:

import React, { useState, useEffect } from 'react';

// 自定义 Hook
function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return width;
}

function DisplayWidth() {
  const width = useWindowWidth();

  return <p>窗口宽度: {width}px</p>;
}

export default DisplayWidth;

4. 组件生命周期管理

在函数组件中,useEffect Hook 用于管理组件的生命周期。通过依赖项数组,可以控制副作用的执行时机,模拟类组件的生命周期方法。

4.1 使用 useEffect 模拟生命周期方法

挂载阶段(componentDidMount):

useEffect(() => {
  // 仅在组件挂载时执行
  console.log('组件已挂载');
}, []); // 空依赖项数组

更新阶段(componentDidUpdate):

useEffect(() => {
  // 在特定依赖项变化时执行
  console.log('依赖项发生变化');
}, [dependency]);

卸载阶段(componentWillUnmount):

useEffect(() => {
  // 返回一个清理函数
  return () => {
    console.log('组件即将卸载');
  };
}, []); // 空依赖项数组

结合挂载和卸载:

useEffect(() => {
  console.log('组件已挂载');

  return () => {
    console.log('组件即将卸载');
  };
}, []);

对比 Vue 3 生命周期:

  • 组件挂载onMounted 相当于 componentDidMount
  • 组件更新onUpdated 相当于 componentDidUpdate
  • 组件卸载onBeforeUnmount 相当于 componentWillUnmount
  • 副作用:Vue 3 的 watchwatchEffect 与 React 的 useEffect 类似。

5. 组件组合与复用

组件组合是 React 的核心思想之一,通过组合小而独立的组件来构建复杂的 UI。函数组件在组合和复用方面具有很大的优势,特别是通过自定义 Hooks 实现逻辑复用。

5.1 组件组合

通过嵌套组件,将复杂的 UI 分解为更小的可管理部分。

示例:

function Header() {
  return <header>Header 部分</header>;
}

function Footer() {
  return <footer>Footer 部分</footer>;
}

function Layout({ children }) {
  return (
    <div>
      <Header />
      <main>{children}</main>

      <Footer />
    </div>

  );
}

function App() {
  return (
    <Layout>
      <h1>欢迎使用 React</h1>

    </Layout>

  );
}

export default App;

5.2 高阶组件(HOC)

高阶组件是一个函数,接收一个组件并返回一个新的组件,用于复用组件逻辑。

示例:

import React from 'react';

// 高阶组件
function withLoading(Component) {
  return function WithLoadingComponent({ isLoading, ...props }) {
    if (isLoading) return <p>加载中...</p>;
    return <Component {...props} />;
  };
}

// 使用高阶组件
function DataDisplay({ data }) {
  return <div>数据: {data}</div>;
}

const DataDisplayWithLoading = withLoading(DataDisplay);

// 在父组件中使用
function App() {
  const [isLoading, setIsLoading] = useState(true);
  const data = "这里是数据";

  useEffect(() => {
    setTimeout(() => setIsLoading(false), 2000);
  }, []);

  return <DataDisplayWithLoading isLoading={isLoading} data={data} />;
}

export default App;

5.3 Render Props

Render Props 是一种通过将函数作为 prop 传递给组件,以便在组件内部使用该函数渲染内容的模式。

示例:

import React, { useState, useEffect } from 'react';

function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(setData);
  }, [url]);

  return render(data);
}

function App() {
  return (
    <DataFetcher
      url="https://api.example.com/data"
      render={data => (data ? <div>数据: {JSON.stringify(data)}</div> : <p>加载中...</p>)}
    />
  );
}

export default App;

5.4 自定义 Hooks

自定义 Hooks 是复用组件逻辑的最佳方式。通过将逻辑提取到自定义 Hooks 中,可以在多个组件中共享。

示例:

import React, { useState, useEffect } from 'react';

// 自定义 Hook
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

function DataDisplay({ url }) {
  const { data, loading } = useFetch(url);

  if (loading) return <p>加载中...</p>;
  return <div>数据: {JSON.stringify(data)}</div>;
}

function App() {
  return <DataDisplay url="https://api.example.com/data" />;
}

export default App;

对比 Vue 3:

Vue 3 的组合式 API 通过 setup 函数和组合函数实现逻辑复用,功能上与 React 的自定义 Hooks 类似。


6. 性能优化

函数组件结合 Hooks 提供了多种性能优化手段,确保应用高效运行。

6.1 React.memo

React.memo 是一个高阶组件,用于防止函数组件在接收到相同 Props 时重新渲染。

示例:

import React, { useState } from 'react';

const ExpensiveComponent = React.memo(({ onClick }) => {
  console.log('ExpensiveComponent 渲染');
  return <button onClick={onClick}>Click Me</button>;
});

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(count + 1);

  return (
    <div>
      <p>计数: {count}</p>

      <ExpensiveComponent onClick={handleClick} />
    </div>

  );
}

export default Parent;

解释:

  • ExpensiveComponent 使用 React.memo 包裹,只在 Props 变化时重新渲染。
  • 如果 onClick 的引用不变,ExpensiveComponent 不会重新渲染,即使父组件重新渲染。

6.2 useMemouseCallback

  • useMemo:缓存计算结果,避免昂贵的计算在每次渲染时重复执行。
  • useCallback:缓存函数定义,防止在每次渲染时创建新的函数引用。

useMemo 示例:

import React, { useState, useMemo } from 'react';

function Fibonacci({ n }) {
  const fib = useMemo(() => {
    const calculateFib = (num) => {
      if (num <= 1) return 1;
      return calculateFib(num - 1) + calculateFib(num - 2);
    };
    return calculateFib(n);
  }, [n]);

  return <div>Fibonacci({n}) = {fib}</div>;
}

function App() {
  const [num, setNum] = useState(10);
  return (
    <div>
      <Fibonacci n={num} />
      <button onClick={() => setNum(num + 1)}>增加</button>

    </div>

  );
}

export default App;

useCallback 示例:

import React, { useState, useCallback } from 'react';

const Child = React.memo(({ onClick }) => {
  console.log('Child 渲染');
  return <button onClick={onClick}>Click Me</button>;
});

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []); // 空依赖项,函数引用不变

  return (
    <div>
      <p>计数: {count}</p>

      <Child onClick={handleClick} />
    </div>

  );
}

export default Parent;

解释:

  • useMemo 缓存 Fibonacci 计算结果,避免重复计算。
  • useCallback 缓存 handleClick 函数引用,防止子组件因函数引用变化而重新渲染。

6.3 懒加载组件

通过动态导入(React.lazy)和 Suspense 实现组件的懒加载,优化初始加载时间。

示例:

import React, { Suspense } from 'react';

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

function App() {
  return (
    <div>
      <h1>主应用</h1>

      <Suspense fallback={<div>加载中...</div>}>
        <LazyComponent />
      </Suspense>

    </div>

  );
}

export default App;

解释:

  • LazyComponent 只有在渲染时才被加载,减少初始包大小。
  • Suspense 提供加载中的回退界面。

7. TypeScript 与函数组件

使用 TypeScript 可以为函数组件提供静态类型检查,提升代码的可靠性和开发体验。通过定义 Props 的接口,可以明确组件的输入和输出。

示例:

import React from 'react';

interface GreetingProps {
  name: string;
  age?: number; // 可选属性
}

const Greeting: React.FC<GreetingProps> = ({ name, age }) => {
  return (
    <div>
      <h1>Hello, {name}!</h1>

      {age && <p>Age: {age}</p>}
    </div>

  );
};

export default Greeting;

使用组件:

import React from 'react';
import Greeting from './Greeting';

function App() {
  return <Greeting name="Alice" age={30} />;
}

export default App;

解释:

  • 定义了 GreetingProps 接口,明确了 name 为必需属性,age 为可选属性。
  • 使用 React.FC<GreetingProps> 进行类型检查,确保传递的 Props 符合接口定义。

对比 Vue 3:

Vue 3 在使用 TypeScript 时,通常通过 defineProps 和组件的类型注解来实现。

<script lang="ts" setup>
interface GreetingProps {
  name: string;
  age?: number;
}

const props = defineProps<GreetingProps>();
</script>

<template>
  <div>
    <h1>Hello, {{ props.name }}!</h1>

    <p v-if="props.age">Age: {{ props.age }}</p>

  </div>

</template>

8. 与 Vue 3 组合式 API 的对比

对于熟悉 Vue 3 组合式 API 的开发者而言,React 的函数组件与 Hooks 有许多相似之处,但也有一些差异。

8.1 逻辑复用

  • Vue 3:使用组合函数(composables)在 setup 中复用逻辑。
  • React:使用自定义 Hooks 在函数组件中复用逻辑。

Vue 3 示例:

<script setup>
import { ref } from 'vue';
import useCounter from './useCounter';

const { count, increment, decrement } = useCounter();
</script>

<template>
  <div>
    <p>Count: {{ count }}</p>

    <button @click="increment">增加</button>

    <button @click="decrement">减少</button>

  </div>

</template>

React 示例:

// useCounter.js
import { useState } from 'react';

function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(c => c + 1);
  const decrement = () => setCount(c => c - 1);
  return { count, increment, decrement };
}

export default useCounter;
// Counter.js
import React from 'react';
import useCounter from './useCounter';

function Counter() {
  const { count, increment, decrement } = useCounter();

  return (
    <div>
      <p>Count: {count}</p>

      <button onClick={increment}>增加</button>

      <button onClick={decrement}>减少</button>

    </div>

  );
}

export default Counter;

8.2 响应式系统

  • Vue 3:内置响应式系统,使用 refreactive 自动追踪依赖。
  • React:基于状态更新触发重新渲染,没有内置的响应式系统,需要手动管理依赖。

8.3 组件声明

  • Vue 3:通过 <script setup>setup 函数声明组件逻辑。
  • React:通过函数定义和 Hooks 声明组件逻辑。

8.4 生命周期管理

  • Vue 3:使用 onMountedonUpdatedonUnmounted 等生命周期函数。
  • React:使用 useEffect 等 Hooks 管理生命周期。

Vue 3 示例:

<script setup>
import { onMounted, onUnmounted } from 'vue';

onMounted(() => {
  console.log('组件已挂载');
});

onUnmounted(() => {
  console.log('组件即将卸载');
});
</script>

React 示例:

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('组件已挂载');

    return () => {
      console.log('组件即将卸载');
    };
  }, []);

  return <div>My Component</div>;
}

export default MyComponent;

8.5 模板 vs JSX

  • Vue 3:使用模板语法(基于 HTML),通过指令(如 v-ifv-for)进行逻辑控制。
  • React:使用 JSX(JavaScript 语法扩展),将逻辑和模板结合在一起。

Vue 3 示例:

<template>
  <div>
    <p v-if="count > 0">Count: {{ count }}</p>

    <button @click="increment">增加</button>

  </div>

</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);
const increment = () => count.value++;
</script>

React 示例:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(c => c + 1);

  return (
    <div>
      {count > 0 && <p>Count: {count}</p>}
      <button onClick={increment}>增加</button>

    </div>

  );
}

export default Counter;

9. 最佳实践

遵循最佳实践可以提升代码质量、可维护性和性能。以下是一些在 React 函数组件中使用 Hooks 和组件组合的最佳实践。

9.1 遵循 Hook 规则

  • 只在顶层调用 Hook:不要在循环、条件或嵌套函数中调用 Hooks。
  • 只在 React 函数组件或自定义 Hooks 中调用 Hook

9.2 分离逻辑与 UI

通过自定义 Hooks 将业务逻辑与 UI 分离,提高代码的复用性和可测试性。

示例:

// useFetch.js
import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let isMounted = true;
    fetch(url)
      .then(res => res.json())
      .then(data => {
        if (isMounted) {
          setData(data);
          setLoading(false);
        }
      });
    return () => { isMounted = false };
  }, [url]);

  return { data, loading };
}

export default useFetch;
// DataDisplay.js
import React from 'react';
import useFetch from './useFetch';

function DataDisplay({ url }) {
  const { data, loading } = useFetch(url);

  if (loading) return <p>加载中...</p>;
  return <div>数据: {JSON.stringify(data)}</div>;
}

export default DataDisplay;

9.3 使用 useCallbackuseMemo 优化性能

合理使用 useCallback 缓存函数引用,使用 useMemo 缓存计算结果,避免不必要的重新渲染和计算。

示例:

import React, { useState, useCallback, useMemo } from 'react';

const ExpensiveComponent = React.memo(({ compute, onClick }) => {
  console.log('ExpensiveComponent 渲染');
  const result = compute();
  return (
    <div>
      <p>计算结果: {result}</p>

      <button onClick={onClick}>增加</button>

    </div>

  );
});

function Parent() {
  const [count, setCount] = useState(0);
  const [other, setOther] = useState(false);

  const compute = useMemo(() => () => {
    // 模拟昂贵的计算
    let total = 0;
    for (let i = 0; i < 1000000; i++) {
      total += i;
    }
    return total + count;
  }, [count]);

  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>

      <ExpensiveComponent compute={compute} onClick={handleClick} />
      <button onClick={() => setOther(!other)}>切换其他状态</button>

    </div>

  );
}

export default Parent;

解释:

  • useMemo 缓存 compute 函数,避免在 count 不变时重新计算。
  • useCallback 缓存 handleClick 函数引用,防止 ExpensiveComponent 不必要的重新渲染。

9.4 管理副作用的清理

useEffect 中正确处理副作用的清理,避免内存泄漏和意外行为。

示例:

useEffect(() => {
  const subscription = subscribeToData((data) => {
    setData(data);
  });

  return () => {
    subscription.unsubscribe();
  };
}, []);

9.5 使用 PropTypes 或 TypeScript 进行类型检查

确保组件接收到的 Props 类型正确,避免运行时错误。

使用 PropTypes:

import PropTypes from 'prop-types';

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
};

export default Greeting;

使用 TypeScript:

interface GreetingProps {
  name: string;
}

const Greeting: React.FC<GreetingProps> = ({ name }) => <h1>Hello, {name}!</h1>;

export default Greeting;

9.6 避免 Prop Drilling

使用 Context API 或状态管理库(如 Redux、MobX、Zustand)管理全局状态,避免多层组件传递 Props。

示例:

// ThemeContext.js
import React, { createContext, useContext, useState } from 'react';

const ThemeContext = createContext();

export function useTheme() {
  return useContext(ThemeContext);
}

export function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>

  );
}
// ThemedComponent.js
import React from 'react';
import { useTheme } from './ThemeContext';

function ThemedComponent() {
  const { theme, setTheme } = useTheme();
  return (
    <div className={theme}>
      <p>当前主题: {theme}</p>

      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        切换主题
      </button>

    </div>

  );
}

export default ThemedComponent;
// App.js
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import ThemedComponent from './ThemedComponent';

function App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>

  );
}

export default App;

10. 高级主题

10.1 并发模式

React 的并发模式允许 React 在多个任务之间切换,以确保应用保持响应性。它通过调度和优先级管理,实现更高效的渲染。

使用并发特性的示例:

import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(c => c + 1);

  return (
    <div>
      <p>Count: {count}</p>

      <button onClick={handleClick}>增加</button>

    </div>

  );
}

const root = createRoot(document.getElementById('root'));
root.render(<App />);

解释:

  • 使用 createRoot 启用并发模式。
  • React 会自动优化渲染,保持应用的流畅性。

10.2 Suspense

Suspense 允许组件在等待异步操作(如数据获取、代码分割)完成时显示备用内容。

示例:

import React, { Suspense } from 'react';

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

function App() {
  return (
    <div>
      <h1>主应用</h1>

      <Suspense fallback={<div>加载中...</div>}>
        <LazyComponent />
      </Suspense>

    </div>

  );
}

export default App;

解释:

  • LazyComponent 在渲染时被动态加载。
  • Suspense 显示 fallback 内容,直到 LazyComponent 加载完成。

10.3 Server Components

React Server Components 是一种允许在服务器上渲染组件的实验性特性,旨在提升性能和开发体验。

示例:

// ServerComponent.server.js
import React from 'react';

export default function ServerComponent() {
  const data = fetchDataFromServer(); // 服务器端数据获取
  return <div>服务器数据: {data}</div>;
}
// ClientComponent.js
import React from 'react';
import ServerComponent from './ServerComponent.server';

function ClientComponent() {
  return (
    <div>
      <h1>客户端组件</h1>

      <ServerComponent />
    </div>

  );
}

export default ClientComponent;

解释:

  • ServerComponent 在服务器端渲染,减少客户端的 JavaScript 负担。
  • ClientComponent 组合使用服务器组件,实现更高效的数据渲染。

注意: Server Components 目前仍处于实验阶段,需关注 React 官方文档以获取最新信息。


11. 总结

React 函数组件结合 Hooks 提供了一种强大而灵活的方式来构建现代 Web 应用。与 Vue 3 的组合式 API 相似,React 的函数组件强调逻辑复用、组件组合和简洁性,但在实现细节和生态系统中也存在差异。通过深入理解函数组件、Hooks、组件生命周期、性能优化和高级主题,开发者可以构建高效、可维护且响应迅速的 React 应用。

关键要点:

  • 简洁性与可读性:函数组件通常比类组件更简洁,易于理解和维护。
  • Hooks 的力量:Hooks(如 useStateuseEffectuseContext)赋予函数组件管理状态和副作用的能力。
  • 逻辑复用:通过自定义 Hooks,实现逻辑的高效复用和代码的模块化。
  • 性能优化:合理使用 React.memouseMemouseCallback 等工具,提升应用性能。
  • 类型安全:结合 TypeScript,增强代码的类型安全和开发体验。
  • 与 Vue 3 的对比:理解两者在状态管理、生命周期管理、组件组合等方面的异同,有助于快速上手 React。

通过本文的深入解析,你应该能够全面掌握 React 函数组件的核心概念和高级用法,并将这些知识应用于实际项目中,构建出高效、可维护的 React 应用。