Skip to content

React API 详细文档

本文档详细介绍React的所有API,包括它们的作用、实现原理、区别和使用场景。

目录

核心API

React.createElement()

作用:创建一个React元素。

实现原理

  • 接收三个参数:type(元素类型)、props(属性)、children(子元素)
  • 返回一个React元素对象,包含type、props等信息
  • 是JSX语法的底层实现

使用场景

  • 当需要动态创建React元素时
  • 当不使用JSX语法时

示例

jsx
const element = React.createElement(
  'div',
  { className: 'container' },
  'Hello World'
)

React.cloneElement()

作用:克隆并返回一个新的React元素,新元素会保留原始元素的props,并可以添加新的props。

实现原理

  • 接收三个参数:element(要克隆的元素)、props(新的属性)、children(新的子元素)
  • 合并原始元素的props和新的props
  • 返回一个新的React元素

使用场景

  • 当需要基于现有元素创建一个稍有不同的新元素时
  • 当需要向子元素传递额外的props时

示例

jsx
const clonedElement = React.cloneElement(element, { id: 'new-id' })

React.createFactory()

作用:创建一个React元素工厂函数。

实现原理

  • 接收一个type参数,返回一个函数
  • 调用返回的函数时,会创建并返回一个指定类型的React元素

使用场景

  • 当需要创建多个相同类型的React元素时
  • 已被JSX语法替代,现在较少使用

示例

jsx
const divFactory = React.createFactory('div')
const element = divFactory({ className: 'container' }, 'Hello World')

React.isValidElement()

作用:检查一个值是否为有效的React元素。

实现原理

  • 接收一个参数,检查它是否是一个React元素对象
  • 判断该对象是否有$$typeof属性且值为Symbol.for('react.element')

使用场景

  • 当需要验证一个值是否为React元素时
  • 在处理可能是React元素也可能是其他类型值的情况下

示例

jsx
const isElement = React.isValidElement(element)

React.Children

作用:提供用于处理React子元素的工具方法。

实现原理

  • 包含map、forEach、count、only、toArray等方法
  • 处理各种子元素情况,包括单个元素、数组、null、undefined等

使用场景

  • 当需要遍历或操作组件的子元素时
  • 当需要处理子元素的各种边缘情况时

示例

jsx
const childrenArray = React.Children.toArray(this.props.children)

React.Fragment

作用:允许将多个元素组合在一起,而不需要额外的DOM节点。

实现原理

  • 是一个特殊的React元素,不会在DOM中渲染
  • 可以包含多个子元素
  • 可以使用key属性

使用场景

  • 当需要返回多个元素但不想添加额外的DOM节点时
  • 当需要在列表中使用key属性时

示例

jsx
<React.Fragment>
  <div>First</div>
  <div>Second</div>
</React.Fragment>

React.StrictMode

作用:用于在开发模式下检测潜在问题。

实现原理

  • 不渲染任何可见元素
  • 在开发模式下,会额外运行一些检查和警告
  • 帮助发现不安全的生命周期方法、过时的API等

使用场景

  • 在开发模式下包裹应用或组件,以检测潜在问题
  • 不影响生产环境的行为

示例

jsx
<React.StrictMode>
  <App />
</React.StrictMode>

React.Suspense

作用:用于处理组件的加载状态。

实现原理

  • 可以包裹懒加载的组件
  • 当组件正在加载时,显示fallback属性指定的内容
  • 与React.lazy()配合使用

使用场景

  • 当需要懒加载组件时
  • 当需要在组件加载过程中显示加载状态时

示例

jsx
<React.Suspense fallback={<div>Loading...</div>}>
  <LazyComponent />
</React.Suspense>

React.lazy()

作用:用于懒加载组件。

实现原理

  • 接收一个函数,该函数返回一个Promise,Promise解析为一个React组件
  • 当组件首次渲染时,会加载该组件
  • 与React.Suspense配合使用

使用场景

  • 当需要按需加载组件以减少初始加载时间时
  • 当组件较大且不总是需要时

示例

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

React.memo()

作用:用于优化函数组件的渲染性能。

实现原理

  • 接收一个函数组件和一个比较函数
  • 当组件的props没有变化时,会跳过渲染
  • 使用浅比较来比较props

使用场景

  • 当组件的渲染成本较高且props变化不频繁时
  • 当组件的props是基本类型且变化较少时

示例

jsx
const MemoizedComponent = React.memo(MyComponent)

组件API

Component 类

作用:React组件的基类,用于创建类组件。

实现原理

  • 提供setState()方法用于更新状态
  • 提供生命周期方法
  • 管理组件的状态和渲染

使用场景

  • 当需要使用生命周期方法时
  • 当组件的状态管理较复杂时
  • 当需要访问this关键字时

示例

jsx
class MyComponent extends React.Component {
  render() {
    return <div>{this.props.name}</div>
  }
}

PureComponent 类

作用:Component的子类,用于优化渲染性能。

实现原理

  • 自动实现了shouldComponentUpdate()方法
  • 使用浅比较来比较props和state
  • 当props和state没有变化时,跳过渲染

使用场景

  • 当组件的props和state是基本类型且变化较少时
  • 当组件的渲染成本较高时
  • 当不需要自定义shouldComponentUpdate()逻辑时

示例

jsx
class MyPureComponent extends React.PureComponent {
  render() {
    return <div>{this.props.name}</div>
  }
}

DOM API

ReactDOM.render()

作用:将React元素渲染到DOM中。

实现原理

  • 接收三个参数:element(React元素)、container(DOM容器)、callback(回调函数)
  • 将React元素转换为DOM元素并插入到容器中
  • 当组件更新时,会执行差异比较并只更新变化的部分

使用场景

  • 当需要将React应用渲染到DOM中时
  • 当需要在现有DOM中插入React组件时

示例

jsx
ReactDOM.render(<App />, document.getElementById('root'))

ReactDOM.hydrate()

作用:用于服务端渲染的应用,将服务器生成的HTML与客户端React代码进行关联。

实现原理

  • 与render()方法类似,但会保留服务器生成的HTML
  • 只添加事件监听器和执行必要的更新
  • 提高首屏加载性能

使用场景

  • 当应用使用服务端渲染时
  • 当需要将服务器生成的HTML与客户端React代码关联时

示例

jsx
ReactDOM.hydrate(<App />, document.getElementById('root'))

ReactDOM.unmountComponentAtNode()

作用:从DOM中卸载React组件。

实现原理

  • 接收一个DOM容器参数
  • 从容器中移除React组件
  • 清理组件的事件监听器和状态

使用场景

  • 当需要手动卸载React组件时
  • 当组件不再需要时

示例

jsx
ReactDOM.unmountComponentAtNode(document.getElementById('root'))

ReactDOM.createPortal()

作用:将子元素渲染到DOM中的任意位置。

实现原理

  • 接收两个参数:children(子元素)、container(DOM容器)
  • 子元素会被渲染到指定的容器中,但仍然是React组件树的一部分
  • 事件会正确冒泡到父组件

使用场景

  • 当需要将组件渲染到DOM中的其他位置时
  • 当需要创建模态框、弹出菜单等组件时

示例

jsx
ReactDOM.createPortal(
  <div>Portal content</div>,
  document.getElementById('portal-container')
)

事件API

React合成事件系统

作用:提供跨浏览器一致的事件处理机制。

实现原理

  • 事件委托:将事件监听器添加到document上
  • 事件池:重用事件对象以提高性能
  • 标准化事件属性和方法

使用场景

  • 当需要处理用户交互事件时
  • 当需要跨浏览器兼容的事件处理时

示例

jsx
function MyComponent() {
  const handleClick = e => {
    console.log('Clicked')
  }

  return <button onClick={handleClick}>Click me</button>
}

Hooks API

基本Hooks

React.useState()

作用:在函数组件中添加状态。

实现原理

  • 接收一个初始状态值
  • 返回一个数组,包含当前状态和更新状态的函数
  • 当状态更新时,组件会重新渲染

使用场景

  • 当函数组件需要状态时
  • 当需要在组件中保存和更新数据时

示例

jsx
function MyComponent() {
  const [count, setCount] = React.useState(0)

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}

React.useEffect()

作用:在函数组件中执行副作用操作。

实现原理

  • 接收一个回调函数和一个依赖数组
  • 当组件挂载、更新或卸载时执行回调函数
  • 依赖数组控制回调函数的执行时机

使用场景

  • 当需要在组件挂载后执行操作时
  • 当需要处理副作用,如网络请求、订阅等时
  • 当需要在组件卸载时清理资源时

示例

jsx
function MyComponent() {
  React.useEffect(() => {
    // 执行副作用操作
    return () => {
      // 清理操作
    }
  }, [dependencies])

  return <div>Component</div>
}

React.useContext()

作用:在函数组件中访问Context。

实现原理

  • 接收一个Context对象
  • 返回该Context的当前值
  • 当Context值变化时,组件会重新渲染

使用场景

  • 当需要在组件树中传递数据,而不需要通过props逐层传递时
  • 当多个组件需要访问相同的数据时

示例

jsx
const ThemeContext = React.createContext('light')

function MyComponent() {
  const theme = React.useContext(ThemeContext)

  return <div>Current theme: {theme}</div>
}

额外Hooks

React.useReducer()

作用:在函数组件中使用reducer来管理状态。

实现原理

  • 接收一个reducer函数和初始状态
  • 返回一个数组,包含当前状态和dispatch函数
  • 当dispatch一个action时,reducer函数会处理action并返回新的状态

使用场景

  • 当状态管理较复杂时
  • 当状态更新依赖于之前的状态时
  • 当需要处理多个相关的状态更新时

示例

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

function MyComponent() {
  const [state, dispatch] = React.useReducer(reducer, { count: 0 })

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  )
}

React.useCallback()

作用:返回一个 memoized 回调函数。

实现原理

  • 接收一个回调函数和一个依赖数组
  • 当依赖数组中的值不变时,返回相同的回调函数引用
  • 避免不必要的重新渲染

使用场景

  • 当需要将回调函数作为props传递给子组件时
  • 当子组件使用React.memo()优化时
  • 当回调函数创建成本较高时

示例

jsx
function MyComponent() {
  const handleClick = React.useCallback(() => {
    console.log('Clicked')
  }, [])

  return <ChildComponent onClick={handleClick} />
}

React.useMemo()

作用:返回一个 memoized 值。

实现原理

  • 接收一个计算函数和一个依赖数组
  • 当依赖数组中的值不变时,返回缓存的值
  • 避免不必要的重新计算

使用场景

  • 当需要进行昂贵的计算时
  • 当计算结果需要作为props传递给子组件时
  • 当计算结果依赖于某些值时

示例

jsx
function MyComponent({ a, b }) {
  const result = React.useMemo(() => {
    // 昂贵的计算
    return a + b
  }, [a, b])

  return <div>Result: {result}</div>
}

React.useRef()

作用:在函数组件中创建一个可变的ref对象。

实现原理

  • 接收一个初始值
  • 返回一个ref对象,包含current属性
  • ref对象在组件的整个生命周期中保持不变
  • 修改ref.current不会触发组件重新渲染

使用场景

  • 当需要访问DOM元素时
  • 当需要在组件之间保存一个可变值,而不需要触发重新渲染时
  • 当需要在useEffect中保存一个值时

示例

jsx
function MyComponent() {
  const inputRef = React.useRef(null)

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

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  )
}

React.useImperativeHandle()

作用:自定义暴露给父组件的ref方法。

实现原理

  • 接收一个ref对象、一个创建句柄的函数和一个依赖数组
  • 允许子组件自定义通过ref暴露给父组件的方法和属性
  • 与React.forwardRef()配合使用

使用场景

  • 当父组件需要调用子组件的方法时
  • 当需要限制子组件暴露给父组件的内容时

示例

jsx
const MyComponent = React.forwardRef((props, ref) => {
  const inputRef = React.useRef(null)

  React.useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus()
    }
  }))

  return <input ref={inputRef} />
})

React.useLayoutEffect()

作用:与useEffect类似,但在DOM更新后同步执行。

实现原理

  • 与useEffect的API相同
  • 但执行时机不同:useLayoutEffect在DOM更新后同步执行,useEffect在浏览器完成绘制后异步执行
  • 适用于需要在DOM更新后立即执行的操作

使用场景

  • 当需要在DOM更新后立即执行操作时
  • 当需要测量DOM元素的尺寸或位置时
  • 当需要避免布局闪烁时

示例

jsx
function MyComponent() {
  const ref = React.useRef(null)

  React.useLayoutEffect(() => {
    // 测量DOM元素
    console.log(ref.current.offsetHeight)
  }, [])

  return <div ref={ref}>Component</div>
}

React.useDebugValue()

作用:在React DevTools中显示自定义Hook的标签。

实现原理

  • 接收一个值和一个格式化函数
  • 在React DevTools中显示该值
  • 仅在开发模式下有效

使用场景

  • 当创建自定义Hook时
  • 当需要在React DevTools中显示有意义的信息时

示例

jsx
function useCustomHook() {
  const [value, setValue] = React.useState(0)

  React.useDebugValue(value > 0 ? 'Positive' : 'Negative')

  return [value, setValue]
}

其他API

React.version

作用:获取当前React的版本号。

实现原理

  • 是一个字符串,包含当前React的版本号
  • 可以用于条件判断或日志记录

使用场景

  • 当需要根据React版本执行不同的代码时
  • 当需要在日志中记录React版本时

示例

jsx
console.log('React version:', React.version)

React.isValidElement()

作用:检查一个值是否为有效的React元素。

实现原理

  • 接收一个参数,检查它是否是一个React元素对象
  • 判断该对象是否有$$typeof属性且值为Symbol.for('react.element')

使用场景

  • 当需要验证一个值是否为React元素时
  • 在处理可能是React元素也可能是其他类型值的情况下

示例

jsx
const isElement = React.isValidElement(element)

React.Children.map()

作用:遍历React子元素并返回一个新的数组。

实现原理

  • 接收children和一个回调函数
  • 对每个子元素执行回调函数
  • 处理各种子元素情况,包括单个元素、数组、null、undefined等

使用场景

  • 当需要遍历并转换子元素时
  • 当需要为每个子元素添加额外的props时

示例

jsx
const newChildren = React.Children.map(this.props.children, (child, index) => {
  return React.cloneElement(child, { key: index })
})

React.Children.forEach()

作用:遍历React子元素并执行回调函数。

实现原理

  • 接收children和一个回调函数
  • 对每个子元素执行回调函数
  • 不返回任何值

使用场景

  • 当需要遍历子元素并执行副作用操作时
  • 当不需要返回新的子元素数组时

示例

jsx
React.Children.forEach(this.props.children, child => {
  console.log(child)
})

React.Children.count()

作用:计算React子元素的数量。

实现原理

  • 接收children参数
  • 返回子元素的数量
  • 处理各种子元素情况,包括单个元素、数组、null、undefined等

使用场景

  • 当需要知道子元素的数量时
  • 当需要根据子元素数量执行不同的逻辑时

示例

jsx
const count = React.Children.count(this.props.children)

React.Children.only()

作用:验证children是否只有一个子元素,并返回该子元素。

实现原理

  • 接收children参数
  • 如果children只有一个子元素,返回该子元素
  • 否则,抛出错误

使用场景

  • 当组件只接受一个子元素时
  • 当需要确保children只有一个子元素时

示例

jsx
const onlyChild = React.Children.only(this.props.children)

React.Children.toArray()

作用:将React子元素转换为一个数组。

实现原理

  • 接收children参数
  • 返回一个包含所有子元素的数组
  • 处理各种子元素情况,包括单个元素、数组、null、undefined等

使用场景

  • 当需要将子元素作为数组处理时
  • 当需要对排序或过滤子元素时

示例

jsx
const childrenArray = React.Children.toArray(this.props.children)

总结

React提供了丰富的API,用于创建和管理组件、处理状态和副作用、操作DOM等。这些API可以分为核心API、组件API、DOM API、事件API和Hooks API等类别。

API对比

API类别主要用途特点
核心API创建和操作React元素提供基础的React元素创建和操作功能
组件API创建和管理组件提供类组件的基类和优化
DOM API操作DOM提供将React元素渲染到DOM的功能
事件API处理用户交互提供跨浏览器一致的事件处理机制
Hooks API在函数组件中使用状态和副作用提供在函数组件中使用状态和副作用的能力

使用建议

  1. 优先使用函数组件和Hooks:函数组件和Hooks是React的现代方式,代码更简洁,更易于理解和维护。

  2. 合理使用React.memo()、useCallback()和useMemo():这些API可以优化组件的渲染性能,但不要过度使用,以免增加代码复杂性。

  3. 使用Context API管理全局状态:当多个组件需要访问相同的数据时,使用Context API可以避免props逐层传递。

  4. 使用React.lazy()和React.Suspense实现代码分割:这可以减少初始加载时间,提高应用性能。

  5. 遵循React的最佳实践:如使用key属性、避免在render中创建函数、正确处理副作用等。

通过合理使用React的各种API,可以创建高性能、可维护的React应用。

基于 VitePress 的本地知识库