当前位置: 首页 > article >正文

【前端】深入浅出的React.js详解

React 是一个用于构建用户界面的 JavaScript 库,由 Facebook 开发并维护。随着 React 的不断演进,官方文档也在不断更新和完善。本文将详细解读最新的 React 官方文档,涵盖核心概念、新特性、最佳实践等内容,帮助开发者更好地理解和使用 React。
在这里插入图片描述

1. React 核心概念
1.1 组件

组件是 React 应用的基本构建块。组件可以是类组件或函数组件,每个组件负责渲染一部分用户界面。

1.1.1 函数组件

函数组件是最简单的组件形式,接受输入(props)并返回 JSX。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
1.1.2 类组件

类组件是通过继承 React.Component 类来定义的,可以包含状态和生命周期方法。

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
1.2 JSX

JSX 是一种在 JavaScript 中编写类似 HTML 代码的语法扩展。React 使用 JSX 来描述 UI 的结构。

const element = <h1>Hello, world!</h1>;
1.3 Props

Props 是组件之间传递数据的方式。父组件通过 props 将数据传递给子组件。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
1.4 State

State 是组件内部的数据存储,用于跟踪组件的状态变化。状态的变化会触发组件的重新渲染。

1.4.1 类组件中的状态

在类组件中,状态通过 state 属性来管理。

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

  increment = () => {
    this.setState(prevState => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}
1.4.2 函数组件中的状态

在函数组件中,使用 useState 钩子来管理状态。

import React, { useState } from 'react';

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

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
2. 新特性
2.1 Concurrent Mode

Concurrent Mode 是 React 的一个实验性功能,旨在提高应用的响应性和性能。Concurrent Mode 允许 React 在后台执行工作,并在必要时中断和恢复这些工作。

2.1.1 Suspense

Suspense 是 Concurrent Mode 的一个重要特性,用于处理异步数据加载。通过 Suspense 组件,可以在数据加载完成之前显示一个加载指示器。

import React, { Suspense } from 'react';
import { fetchData } from './api';

function DataFetcher() {
  const data = useDataLoader();

  return <p>Data: {data}</p>;
}

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

function useDataLoader() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then(data => setData(data));
  }, []);

  if (!data) {
    throw new Promise(resolve => setTimeout(resolve, 1000));
  }

  return data;
}
2.2 Hooks

Hooks 是 React 16.8 引入的新特性,允许在函数组件中使用状态和其他 React 特性。

2.2.1 useState

useState 钩子用于在函数组件中添加状态。

import React, { useState } from 'react';

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

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
2.2.2 useEffect

useEffect 钩子用于在函数组件中执行副作用操作,如发起网络请求、设置定时器等。

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

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

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      {data ? (
        <p>Data: {data}</p>
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
}
2.2.3 useContext

useContext 钩子用于在函数组件中使用 Context。

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

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>Button</button>;
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}
3. 生命周期方法

生命周期方法是类组件中的一系列方法,用于在组件的不同阶段执行特定的操作。函数组件中使用钩子来实现类似的功能。

3.1 类组件中的生命周期方法
3.1.1 componentDidMount

在组件挂载后立即调用,通常用于发起网络请求或设置定时器。

class DataFetcher extends React.Component {
  state = {
    data: null
  };

  componentDidMount() {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  }

  render() {
    return (
      <div>
        {this.state.data ? (
          <p>Data: {this.state.data}</p>
        ) : (
          <p>Loading...</p>
        )}
      </div>
    );
  }
}
3.1.2 componentDidUpdate

在组件更新后立即调用,可以用于比较新旧状态或属性,执行相应的操作。

class DataFetcher extends React.Component {
  state = {
    data: null,
    id: 1
  };

  componentDidUpdate(prevProps, prevState) {
    if (prevState.id !== this.state.id) {
      fetch(`https://api.example.com/data/${this.state.id}`)
        .then(response => response.json())
        .then(data => this.setState({ data }));
    }
  }

  changeId = () => {
    this.setState(prevState => ({ id: prevState.id + 1 }));
  };

  render() {
    return (
      <div>
        {this.state.data ? (
          <p>Data: {this.state.data}</p>
        ) : (
          <p>Loading...</p>
        )}
        <button onClick={this.changeId}>Change ID</button>
      </div>
    );
  }
}
3.1.3 componentWillUnmount

在组件卸载前调用,通常用于清理定时器或取消网络请求。

class Timer extends React.Component {
  state = {
    seconds: 0
  };

  interval = null;

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState(prevState => ({ seconds: prevState.seconds + 1 }));
    }, 1000);
  }

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

  render() {
    return <p>Seconds: {this.state.seconds}</p>;
  }
}
3.2 函数组件中的生命周期方法
3.2.1 useEffect

useEffect 钩子用于在函数组件中执行副作用操作,如发起网络请求、设置定时器等。

3.2.1.1 模拟 componentDidMount

在组件挂载后执行操作:

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

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

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // 空数组表示只在组件挂载时执行一次

  return (
    <div>
      {data ? (
        <p>Data: {data}</p>
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
}
3.2.1.2 模拟 componentDidUpdate

在组件更新后执行操作:

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

function DataFetcher() {
  const [data, setData] = useState(null);
  const [id, setId] = useState(1);

  useEffect(() => {
    fetch(`https://api.example.com/data/${id}`)
      .then(response => response.json())
      .then(data => setData(data));
  }, [id]); // 依赖数组包含 id,表示当 id 变化时重新执行

  const changeId = () => {
    setId(id + 1);
  };

  return (
    <div>
      {data ? (
        <p>Data: {data}</p>
      ) : (
        <p>Loading...</p>
      )}
      <button onClick={changeId}>Change ID</button>
    </div>
  );
}
3.2.1.3 模拟 componentWillUnmount

在组件卸载前执行清理操作:

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

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    return () => clearInterval(interval); // 清理定时器
  }, []); // 空数组表示只在组件挂载时执行一次

  return <p>Seconds: {seconds}</p>;
}
4. 最佳实践
4.1 代码分割和懒加载

通过代码分割和懒加载,可以优化应用的初始加载时间和性能。

import React, { Suspense, lazy } from 'react';

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

function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}
4.2 避免不必要的渲染

通过 React.memoPureComponent,可以避免不必要的组件重新渲染。

4.2.1 React.memo

React.memo 是一个高阶组件,用于优化函数组件的性能。

import React from 'react';

const MyComponent = React.memo(function MyComponent(props) {
  /* 只在 props 发生变化时重新渲染 */
  return <div>{props.value}</div>;
});
4.2.2 PureComponent

PureComponent 是一个基类,用于优化类组件的性能。

import React from 'react';

class MyComponent extends React.PureComponent {
  render() {
    /* 只在 props 或 state 发生变化时重新渲染 */
    return <div>{this.props.value}</div>;
  }
}
4.3 使用 useMemouseCallback

useMemouseCallback 钩子可以用于优化性能,避免不必要的计算和函数创建。

4.3.1 useMemo

useMemo 用于缓存计算结果,避免不必要的计算。

import React, { useMemo } from 'react';

function MyComponent({ list }) {
  const sortedList = useMemo(() => list.sort(), [list]);

  return <div>{sortedList.join(', ')}</div>;
}
4.3.2 useCallback

useCallback 用于缓存函数,避免不必要的函数创建。

import React, { useCallback } from 'react';

function MyComponent({ onIncrement }) {
  const handleIncrement = useCallback(() => {
    onIncrement();
  }, [onIncrement]);

  return <button onClick={handleIncrement}>Increment</button>;
}
4.4 错误边界

错误边界是一种 React 组件,可以捕获并处理其子组件树中抛出的 JavaScript 错误。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error, errorInfo) {
    logErrorToMyService(error, errorInfo);
  }

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

    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <MyWidget />
    </ErrorBoundary>
  );
}
5. 示例代码

以下是一些综合示例,展示了如何在 React 中使用不同的特性和最佳实践。

5.1 类组件示例
class DataFetcher extends React.Component {
  state = {
    data: null,
    id: 1
  };

  componentDidMount() {
    this.fetchData();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.id !== this.state.id) {
      this.fetchData();
    }
  }

  componentWillUnmount() {
    this.abortController.abort();
  }

  fetchData = () => {
    this.abortController = new AbortController();
    fetch(`https://api.example.com/data/${this.state.id}`, { signal: this.abortController.signal })
      .then(response => response.json())
      .then(data => this.setState({ data }))
      .catch(error => console.error('Fetch error:', error));
  };

  changeId = () => {
    this.setState(prevState => ({ id: prevState.id + 1 }));
  };

  render() {
    return (
      <div>
        {this.state.data ? (
          <p>Data: {this.state.data}</p>
        ) : (
          <p>Loading...</p>
        )}
        <button onClick={this.changeId}>Change ID</button>
      </div>
    );
  }
}
5.2 函数组件示例
import React, { useState, useEffect, useCallback } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  const [id, setId] = useState(1);

  useEffect(() => {
    const abortController = new AbortController();

    fetch(`https://api.example.com/data/${id}`, { signal: abortController.signal })
      .then(response => response.json())
      .then(data => setData(data))
      .catch(error => console.error('Fetch error:', error));

    return () => abortController.abort(); // 清理请求
  }, [id]);

  const changeId = useCallback(() => {
    setId(id + 1);
  }, [id]);

  return (
    <div>
      {data ? (
        <p>Data: {data}</p>
      ) : (
        <p>Loading...</p>
      )}
      <button onClick={changeId}>Change ID</button>
    </div>
  );
}
6. 总结

React 是一个强大的库,用于构建用户界面。通过理解核心概念、新特性和最佳实践,开发者可以更高效地使用 React 构建高性能和响应式的应用。本文详细解读了最新的 React 官方文档,涵盖了组件、JSX、Props、State、生命周期方法、Hooks、Concurrent Mode 等内容,并提供了示例代码和最佳实践。

附录

  • React 官方文档:React 文档
  • React Hooks 文档:React Hooks
  • MDN Web 文档:React 简介

http://www.kler.cn/a/396180.html

相关文章:

  • 数据分析-48-时间序列变点检测之在线实时数据的CPD
  • C#笔记(3)
  • CC6学习记录
  • python os.path.basename(获取路径中的文件名部分) 详解
  • Unity图形学之Blend指令
  • 用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)
  • SpringCloud2023实战之接口服务测试工具SpringBootTest
  • ORB-SLAM2源码学习:ORBextractor.cc:ORBextractor::operator()主入口函数
  • 开源AI大模型工作流神器Flowise本地部署与远程访问
  • VMware高危漏洞VMSA-2024-0019修复堆溢出和权限提升漏洞
  • 最后一个单词的长度---每日小题
  • 【免越狱】iOS砸壳 可下载AppStore任意版本 旧版本IPA下载
  • Spring Boot框架:电商系统的技术革新
  • CSS Grid 布局实战:从入门到精通
  • 推理计算:GPT-o1 和 AI 治理
  • 一文说清C++类型转换操作符(cast operator)
  • datawhale11月组队学习 模型压缩技术2:PyTorch模型剪枝教程
  • 多路转接之poll
  • SpringBoot整合Minio
  • 第二十章 TCP 客户端 服务器通信 - 立即发送模式(Q 模式)
  • react的import 导入语句中的特殊符号
  • Cpolar 内网穿透使用
  • 人群计数制作私有数据集教程-----自用
  • 动力商城-03 Idea集成apifox Mybatis-Plus字段策略
  • 前端开发中的CSS框架:昔日辉煌与新兴潮流
  • 电脑不显示wifi列表怎么办?电脑不显示WiF列表的解决办法