ReactJS 教程

ReactJS 主页 ReactJS 简介 ReactJS 路线图 ReactJS 下载安装和环境配置 ReactJS 功能 ReactJS 优势和缺点 ReactJS 架构 ReactJS 创建 React 应用程序 ReactJS JSX ReactJS 组件 ReactJS 嵌套组件 ReactJS 使用组件 ReactJS 集合组件 ReactJS 样式 ReactJS 属性 (props) ReactJS 使用属性创建组件 ReactJS props 验证 ReactJS 构造函数 ReactJS 组件生命周期 ReactJS 事件管理 ReactJS 创建事件感知组件 ReactJS Expense Manager 事件 ReactJS 状态管理 ReactJS 状态管理 API ReactJS 无状态组件 ReactJS Hooks 进行状态管理 ReactJS Hooks 的组件生命周期 ReactJS 布局组件 ReactJS 分页 ReactJS Material UI ReactJS Http 客户端编程 ReactJS 表单编程 ReactJS 受控组件 ReactJS 非受控组件 ReactJS Formik ReactJS 条件渲染 ReactJS 列表 ReactJS Key 键 ReactJS 路由 ReactJS Redux ReactJS 动画 ReactJS Bootstrap ReactJS Map ReactJS 表格 ReactJS 使用 Flux 管理状态 ReactJS 测试 ReactJS CLI 命令 ReactJS 构建和部署 ReactJS 示例

Hooks

ReactJS Hooks 简介 ReactJS 使用 useState ReactJS 使用 useEffect ReactJS 使用 useContext ReactJS 使用 useRef ReactJS 使用 useReducer ReactJS 使用 useCallback ReactJS 使用 useMemo ReactJS 自定义 Hooks

ReactJS 高级

ReactJS 可访问性 ReactJS 代码拆分 ReactJS 上下文 ReactJS 错误边界 ReactJS 转发 Refs ReactJS 片段 ReactJS 高阶组件 ReactJS 与其他库集成 ReactJS 优化性能 ReactJS Profiler API ReactJS Portals ReactJS 不使用 ES6 ECMAScript ReactJS 不使用 JSX 的 React ReactJS Reconciliation ReactJS Refs 和 DOM ReactJS 渲染道具 ReactJS 静态类型检查 ReactJS 严格模式 ReactJS Web 组件

其他概念

ReactJS 日期选择器 ReactJS Helmet ReactJS 内联样式 ReactJS PropTypes ReactJS BrowserRouter ReactJS DOM ReactJS 轮播 ReactJS 图标 ReactJS 表单组件 ReactJS 参考 API

ReactJS 有用资源

ReactJS 快速指南 ReactJS 备忘录 Axios 备忘录 ReactJS 有用资源 ReactJS 讨论


React 备忘录

此 ReactJS 备忘录 涵盖了重要主题,并附有示例和说明。它专为初学者和经验丰富的开发人员设计,可帮助他们快速学习所有关键的 ReactJS 概念。

目录

什么是 ReactJS?

ReactJS 也称为 React,它是一个开源 JavaScript 库,由 Facebook 于 2013 年开发。它通常用于创建用户界面 (UI),更具体地说,用于创建单页应用程序 (SPA)。React 是一个客户端 JavaScript 库,允许其开发人员使用组件构建引人入胜的 Web 应用程序。

ReactJs 基础知识

reactJs 有以下基本概念 −

1. 组件

组件 是应用程序的构建块。它是一段可重复使用的代码,代表了用户界面的一部分。

让我们创建一个组件。导航到您的项目文件夹,并在 src 文件夹中创建一个扩展名为 .js 或 .jsx 的文件。

import react from 'react';
function Demo() {
  return (
    <>
      <h2>This is Component You can use anywhere in the Application</h2>
      <p>You can use import this component in App.js or App.tsx</p>
    <>
  );
}
export default Demo;

2. 多个导入

您可以将多个模块或组件导入另一个组件或 App.js 来操作您的应用程序。

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import Demo from './Demo'

3. Props

在 ReactJs 中,props 被称为属性。Props 是存储标签属性值的对象。它们用于将数据从一个组件传递到另一个组件,类似于在函数中传递参数的方式。让我们看看如何将 props 分配给组件−

import react from 'react';

// Pass the Props
function Demo(props) {
  return (
    <>
      <h2>This is Component</h2>
      <p>Here in this component we are passing props</p>

      {/* Display the props value */}
      <p>your name: {props.name}</p>
    </>
  );
}
export default Demo;

如何将 Props 值传递给组件

<Demo name={'Aman kumar'} />

4. 在 render() 中解构 props

使用 this.props.name 或 this.props.age 处理类组件时可能很困难。您无需多次编写 this.props.name 和 this.props.age,而是可以使用解构直接从 this.props 分配 name 和 age −

import React from 'react';

class Greeting extends React.Component {
  render() {
    // 解构 props
    const { name, age } = this.props;

    return (
      <div>
        <p>Hello, {name}!</p>
        <p>You are {age} years old.</p>
      </div>
    );
  }
}
//usage
<Greeting name="Alice" age={25} />;

5. PropTypes

在 ReactJs 中,props 类型充当定义 props 类型的方法。这确保为 props 传递正确的数据类型。

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  static propTypes = {
    name: PropTypes.string
  };

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

6. State

在 ReactJs 中,State 是一个内置对象,允许组件随时间存储和操作数据。它是构建动态和交互式用户界面的重要概念。

7. 带构造函数的状态

在 React 中,我们可以在 构造函数 方法中声明组件的状态:

import react from 'react';
class Demo extends react.Component {
  constructor() {
    // 使用 props 调用父类构造函数
    super(props);
    this.sate = {
      // 在这里定义状态
      count: 0,
      message: 'Hello React',
    };
  }
  render() {
    return (
      <div>
        {/* Display the state value */}
        <p>{this.state.count}</p>
        <p>{this.sate.message}</p>
      </div>
    );
  }
}
export default Demo;

8. 无构造函数的状态

我们可以在 React 类组件中定义状态,而无需使用构造函数,方法是使用状态的类字段。

import react from 'react';
class Demo extends react.Component {
  sate = {
    // define state here
    count: 0,
    message: 'Hello React',
  };
  render() {
    return (
      <div>
        {/* Display the state value */}
        <p>Count: {this.state.count}</p>
        <p>Message: {this.sate.message}</p>
      </div>
    );
  }
}
export default Demo;

9. Children

在 ReactJs 中,"children" prop 使我们能够在父组件的开始和结束标签之间直接插入任何组件或内容。

import react from 'react'
function Card ({childre, title}){
  return(
    <div>
      <h2>{title}</h2>
      <div className="card-content"> {children} </div>
    </div>
  )
}

在 App.js 中导入 Card 组件

<Card title="User Details">
   <p>Name: Aman Kumar</p>
   <p>Email: aman.kumar@email.com</p>
</Card>

10. Pure 组件

在 ReactJs 中,纯组件是仅在其 props 和 state 发生变化时才渲染的组件。

class Greeting extends PureComponent {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

11. React 生命周期方法

生命周期有三个阶段,挂载、更新和卸载。以下是方法 −

Sr.No Mounting Updating
1 constructor() shouldComponentUpdate()
2 render() render()
3 componentDidMount() componentDidUpdate()

状态管理

在 ReactJs 中,语句管理是管理数据以及数据在 React 应用程序中跨组件变化的过程。

概念 解释 示例
useState 管理功能组件中的状态。 const [name, setName] = useState("")
Local State(本地状态) 单个组件中使用的状态。 const [count, setCount] = useState(0)
Global State(全局状态) 多个组件共享状态。 const [items, setItems] = useState([]);
Props 将数据/函数从父组件传递给子组件。 <Nav onAddItem={handleAddItem}/>
Event Handling(事件处理) 根据用户操作更新状态。 <button onClick={() => setName("React")}>Click</button>
Updating State(更新状态) 使用 setter 函数更新状态。 setItems([...items, newItem])
State in Children(子级中的状态) 将状态更新函数作为 props 传递给子级。 <Child onToggle={toggleFeature} />
Rendering Lists(渲染列表) 使用状态渲染动态列表。 {list.map(item => <li key={item.id}>{item.name}</li>)}

Hooks

在 ReactJs 中,hooks 允许开发人员使用 React 功能而无需编写类组件。

1. 状态 Hook

useState 是一个 React Hook,可让您向功能组件添加状态变量,此状态可用于跟踪字符串、数字、布尔值、数组、对象以及数据类型的任意组合。

import { useState } from 'react';
function StateHook() {
  // 使用 useState Hooks(钩子)...
  const [count, setCount] = useState(0);

  return (
    <>
      <p>Learn ReactJs useState hooks</p>
      <h2>{count}</h2>
      <button onClick={() => setCount((count) => count + 1)}>Count</button>
    </>
  );
}
export default StateHook;

2. Effect Hook

useEffect 是一个 React Hook,它允许我们将组件与外部系统同步。这意味着它用于处理诸如获取数据和更新 DOM 之类的副作用。

import { useEffect, useState } from 'react';

function UseEffectHook() {
  const [color, setColor] = useState('white');
  const [background, setBackground] = useState(false);

  // 使用 useEffect Hooks(钩子)来改变背景......
  useEffect(() => {
    if (background) {
      const newColor = getRandomColor();
      setColor(newColor);
      setBackground(false);
    }
  }, [background]);

  function getRandomColor() {
    const colors = [
      'red',
      'blue',
      'green',
      'yellow',
      'pink',
      'purple',
      'orange',
    ];
    return colors[Math.floor(Math.random() * color.length)];
  }

  return (
    <>
      <div
        className="myDiv"
        style={{
          height: 'auto',
          width: 'auto',
          margin: '5px',
          padding: '5px',
          background: color,
        }}
      >
        Click the below button to change my Background...
      </div>
      <button onClick={() => setBackground(true)}>Change Background</button>
    </>
  );
}
export default UseEffectHook;

3. 自定义Hooks(钩子)

在 ReactJS 中,自定义Hooks(钩子)是允许我们提取和重用组件逻辑的函数,允许在多个组件之间共享复杂的状态行为。

import react from 'react';
import { useState } from 'react';

// 创建一个自定义Hooks(钩子)...
function UseCustomHook(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  // 创建自定义函数...
  const increment = () => setCount((count = count + 1));
  const decrement = () => setCount((count = count - 1));
  const reset = () => setCount(initialValue);

  return { count, increment, decrement, reset };
}
export default UseCustomHook;

在 App.js 组件中使用自定义Hooks(钩子)

import UseCustomHook from './ReactHooks/CustomHook';

function App() {
  const { count, increment, decrement, reset } = UseCustomHook(0);
  return (
    <>
	<div style={{ textAlign: 'center', marginTop: '50px' }}>
        <h1>Counter: {count}</h1>
        <button onClick={increment} style={{ margin: '5px' }}>
          Increment
        </button>
        <button onClick={decrement} style={{ margin: '5px' }}>
          Decrement
        </button>
        <button onClick={reset} style={{ margin: '5px' }}>
          Reset
        </button>
      </div>
    </>
  );
}
export default App;

React 18 功能

以下是 React 18 功能 −

1. 安装和设置(安装 React 18 和 React DOM)

npm install react react-dom

2. 自动批处理

这是 React 18 的一项功能,通过将多个状态和更新分组到单个渲染中来提高应用程序的性能。

fetch('/api').then(() => {
  setCounter(); // Re-render 1
  setActive();  // Re-render 2
});

3. 转换

React 18 的另一个功能使开发人员能够根据用户预期与更新交互的频率对更新进行优先级排序。它用于区分不需要立即反映的更新。

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

function UseTransition() {
  const [input, setInput] = useState('');
  const [list, setList] = useState([]);
  const [isPending, startTransition] = useTransition();

  const handleInputChange = (e) => {
    const value = e.target.value;
    setInput(value);

    // 使用 startTransition 进行非紧急更新
    startTransition(() => {
      const newList = Array.from(
        { length: 200 },
        (_, i) => `${value} ${i + 1}`
      );
      setList(newList);
    });
  };

  return (
    <div>
      <h3>React 18: startTransition Example</h3>
      <input
        type="text"
        value={input}
        onChange={handleInputChange}
        placeholder="Eneter text..."
      />
      {isPending && <p>Loading...</p>}
      <ul>
        {list.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}
export default UseTransition;

4. 服务器上的 Suspense

此功能允许开发人员在等待数据加载时显示临时或"后备"UI 来管理 UI。一旦数据组件加载完成,就会呈现所需的数据。

<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>

高级功能

以下是 React 的高级功能 −

1. Fragments

在 React 中,Fragments 用于返回组件中的多个元素。Fragments 允许我们将子元素列表分组,而无需向 DOM 添加额外节点。

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

2. Portals

React Portal 允许将子组件渲染到父组件 DOM 层次结构之外的 DOM 节点中。

ReactDOM.createPortal(child, container)

3. React Suspense 和延迟加载

Suspense 和延迟加载的结合实现了高效的代码拆分。众所周知,Suspense 允许开发人员处理异步加载,直到实际组件被渲染。

import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

// 延迟加载组件
const Home = React.lazy(() => import('./Home'));
const Login = React.lazy(() => import('./Login'));

const App = () => {
  return (
    <>
      <Router>
        <Suspense fallback={<div>Loading...</div>}>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/login" element={<Login />} />
          </Routes>
        </Suspense>
      </Router>
    </>
  );
};
export default App;

常见模式

1. 列表

React 中的列表用于使用 .map() 方法动态呈现重复元素

const ItemList = ({ items }) => (
  <ul>
    {items.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>
);

// Usage
<ItemList items={['Apple', 'Banana', 'Cherry']} />;

2. 条件语句

React 中的条件语句根据特定条件确定应渲染的内容。

三元运算符

const Greeting = ({ isLoggedIn }) =>
  isLoggedIn ? <h1>Welcome Back!</h1> : <h1>Please Sign In</h1>;

逻辑与 And (&&)

const Notification = ({ hasNotification }) =>
  hasNotification && 

You have new notifications!

;

if 语句

const StatusMessage = ({ status }) => {
  if (status === 'success') return <p>Operation Successful!</p>;
  if (status === 'error') return <p>Error Occurred!</p>;
  return <p>Loading...</p>;
};

3. Refs(访问 DOM)

Refs 用于直接与 DOM 节点或 React 元素交互。您可以使用 React.createRef() 或 useRef() Hooks(钩子)创建 refs。

import React, { useRef } from 'react';
const FocusInput = () => {
  const inputRef = useRef();

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

  return (
    <>
      <input ref={inputRef} type="text" placeholder="Focus me" />
      <button onClick={focusInput}>Focus</button>
    </>
  );
};

4. 常用方法

以下是 React 的常用方法

方法 说明
setState() 动态更新状态。
forceUpdate() 强制重新渲染。
componentDidCatch(error) 捕获渲染错误。

性能优化

React 提供了几种技术来增强 React 应用程序的性能。

1. React.Memo

它是一个高阶组件,除非 props 发生变化,否则会阻止功能组件的重新渲染。

const ChildComponent = React.memo(({ value }) => {
  console.log('Rendered');
  return <p>{value}</p>;
});

const Parent = () => {
  const [count, setCount] = React.useState(0);
  return (
    <>
      <ChildComponent value="Static Value" />
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </>
  );
};

2. useCallback Hook

此Hooks(钩子)可防止子组件在将函数作为 props 传递时不必要地重新渲染。

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

const Button = React.memo(({ handleClick, children }) => {
  console.log(`Rendering Button: ${children}`);
  return <button onClick={handleClick}>{children}</button>;
});

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

  // useCallback 记忆该函数,这样它就不会在每次渲染时重新创建
  const increment = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []);

  return (
    <div>
      <h1>Count: {count}</h1>
      <Button handleClick={increment}>Increment</Button>
    </div>
  );
};
export default Counter;

3. useMemo Hook

React 中的 useMemo hook,返回一个记忆值,并防止应用程序进行不必要的渲染。在使用函数组件时,它在复杂的计算和处理中很有用。

import React, { useMemo, useState } from 'react';
export default function Square() {
  const [count, setCount] = useState(0);

  // use the useMemo hooks...
  const squareCount = useMemo(() => {
    return count * count;
  }, [count]);

  return (
    <>
      <h2>Square: {squareCount}</h2>
      <button type="button" onClick={() => setCount(count + 1)}>
        ClickMe!
      </button>
    </>
  );
}

React 并发渲染

并发渲染是 React18 的一项功能。这是一项新的渲染功能,可帮助我们的应用程序在高负载下保持响应,并让我们更好地控制更新的安排方式。并发渲染支持 useTransition 和 useDeferredValue Hooks(钩子)。

1. useTransition Hooks(钩子)

React 中的 useTransition Hooks(钩子)允许我们更新组件的状态而不阻塞用户界面 (UI)。

  • isPending:指示转换是否正在进行中。
  • startTransition:将封闭的函数标记为非紧急。
const [isPending, startTransition] = useTransition();
const handleClick = () => {
  startTransition(() => {
    setState(someCalculation());
  });
};

2. useDeferredValue Hook

useDeferredValue 是一个 React hook,它允许我们延迟更新 UI 组件。

import { Suspense, useState, useDeferredValue } from 'react';
import SearchResults from './SearchResults.js';

export default function App() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  return (
    <>
      <label>
        Search albums:
        <input value={query} onChange={e => setQuery(e.target.value)} />
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <SearchResults query={deferredQuery} />
      </Suspense>
    </>
  );
}

代码拆分

代码拆分在 React 中将 JS 包拆分为可按需加载的较小代码块。Webpack、Rollup 和 Browserify 等包支持创建多个包以进行动态运行时加载。

1. 动态 import()

动态导入是一种 JS 功能,允许在运行时而不是编译时异步加载模块。当使用 react.lazy 时,childComponent 代码将被拆分为单独的 JS 文件。

import("./math").then(math => {
  console.log(math.add(16, 26));
});

2. React.lazy

在这里,我们使用 React.lazy 将 React 应用程序拆分成更小的块。

import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
// use React.lazy...
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading Page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}
export default App;

3. Suspense

Suspense 将显示一些默认值,直到应用程序中的某个组件准备好渲染为止。

<Suspense fallback={<div>Loading Page...</div>}>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
  </Routes>
</Suspense>

4. 处理多个惰性组件

我们可以为 code_splitting 处理多个或多个组件 −

<Suspense fallback={<div>Loading...</div>}>
 <OtherComponent />
 <AnotherComponent />
 <AnotherDifferentComponent />
</Suspense>

5. 延迟加载的错误边界

使用延迟加载时,动态导入期间可能会发生错误,例如由于网络问题而无法加载模块。为了有效处理此类情况,我们可以在 React 中使用错误边界。

<ErrorBoundary>
  <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
  </Suspense>
</ErrorBoundary>

高级Hooks(钩子)

React 中有一些高级Hooks(钩子),上面的部分已经讨论了其中一些。

1. useId

useId() 是一个 React Hooks(钩子),用于为可访问性属性生成唯一 ID。

import React, { useId } from 'react';

function Generateid() {
  // 为输入和文本区域生成唯一的 ID
  const inputId = useId();
  const textareaId = useId();

  return (
    <div>
      <h1>Feedback Form</h1>
      <div>
        <label htmlFor={inputId}>Name:</label>
        <input id={inputId} type="text" placeholder="Enter your name" />
      </div>
      <div>
        <label htmlFor={textareaId}>Feedback:</label>
        <textarea
          id={textareaId}
          rows="4"
          placeholder="Enter your feedback"
        ></textarea>
      </div>
    </div>
  );
}
export default Generateid;

2. useImperativeHandle

React 中的 useImperativeHandle Hooks(钩子)用于自定义 React ref 公开的实例值。

import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const CustomInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  // 使用 `useImperativeHandle` 向父类公开方法
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    clear: () => {
      inputRef.current.value = '';
    },
  }));

  return <input ref={inputRef} type="text" placeholder="Type something..." />;
});

export default CustomInput;

App.js

import React, { useRef } from 'react';
import CustomInput from './CustomInput';

function App() {
  const inputRef = useRef();

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

  const handleClear = () => {
    inputRef.current.clear();
  };

  return (
    <div>
      <h1>useImperativeHandle Example</h1>
      <CustomInput ref={inputRef} />
      <button onClick={handleFocus}>Focus Input</button>
      <button onClick={handleClear}>Clear Input</button>
    </div>
  );
}

export default App;

错误边界

错误边界是 React 组件,用于处理其子组件中发生的 JavaScript 错误。它们记录这些错误并提供后备 UI,防止整个应用程序崩溃。

错误边界示例

import React from 'react';
class MyErrorBoundary extends React.Component {
  state = { error: null };

  static getDerivedStateFromError(error) {
    return { error };
  }

  componentDidCatch(error, info) {
    console.error(error, info);
  }

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

export default MyErrorBoundary;

使用错误边界

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

<MyErrorBoundary>
  <BuggyComponent />
</MyErrorBoundary>

TypeScript 集成

将 TypeScript 与 React 集成可实现静态类型,从而增强开发体验。

使用 Vite 的 TypeScript 项目进行 React

此处,分步指南介绍如何使用 vite 设置带有 TypeScript 的 React 项目 −

步骤 1: 运行以下命令创建一个新的 vite 项目 −

npm create vite@latest my-react-ts-app

将 my-react-ts-app 替换为您的项目名称。

步骤 2: 导航到项目目录 −

cd name-of-project(例如 my-react-ts-app)

步骤 3: 安装依赖项 −

npm install

步骤 4: 运行开发服务器 −

npm run dev

步骤 5: 添加自定义 TypeScript 配置:如果需要,更新 tsconfig.json 文件 −

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

步骤 6:创建一个示例组件以供练习 −

import React from 'react';

interface HelloWorldProps {
  message: string;
}

const HelloWorld: React.FC<HelloWorldProps> = ({ message }) => {
  return <h1>{message}</h1>;
};

export default HelloWorld;

步骤 7:在 App.ts 中使用创建的组件−

import React from 'react';
import HelloWorld from './components/HelloWorld';

const App: React.FC = () => {
  return (
    <div>
      <HelloWorld message="Hello, React with TypeScript!" />
    </div>
  );
};

export default App;

现代 React 模式

容器和展示组件

容器组件管理状态和逻辑,而展示组件仅关注 UI。

容器组件:

import React, { useEffect, useState } from 'react';
import CharacterList from './CharacterList';

const DemoContainer: React.FC = () => {
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);
  const [characters, setCharacters] = useState<any[]>([]);

  useEffect(() => {
    const fetchCharacters = async () => {
      try {
        const response = await fetch('https://example.com/api/character/');
        const data = await response.json();
        setCharacters(data.results);
      } catch (err) {
        setError('Failed to fetch characters');
      } finally {
        setLoading(false);
      }
    };

    fetchCharacters();
  }, []);

  return (
    <CharacterList loading={loading} error={error} characters={characters} />
  );
};

export default DemoContainer;

表示组件:CharacterList

import React from 'react';

interface Props {
  loading: boolean;
  error: string | null;
  characters: any[];
}

const CharacterList: React.FC<Props> = ({ loading, error, characters }) => {
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <ul>
      {characters.map((character, index) => (
        <li key={index}>{character.name}</li>
      ))}
    </ul>
  );
};

export default CharacterList;

自定义Hooks(钩子)

自定义Hooks(钩子)包含逻辑和状态管理,使其可跨组件重复使用。

import react, { useEffect, useState } from 'react';
const CustomHook = (url) => {
  const [data, setData] = useState(null);

  // Fetch Api
  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => setData(data));
  }, [url]);
};
export default CustomHook;

测试

React 测试可确保您的组件按预期做出反应,并有助于维护稳健、无错误的代码。

1. 使用 Create React App 进行设置

如果您使用 create-react-app,jest 已预先安装。添加 react-test-renderer 以获取快照 −

npm install --save-dev react-test-renderer

2.无需创建 React App 即可进行设置

手动安装 Jest、Babel 和 React 依赖项 −

npm install --save-dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer

3. 配置 package.json

添加测试脚本和可选的 Jest 配置 −

{
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^29.0.0",
    "babel-jest": "^29.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "react-test-renderer": "^18.0.0"
  },
  "jest": {
    "testEnvironment": "jsdom"
  }
}

4. 创建 Babel 配置 (babel.config.js)

添加 Babel 预设以启用 JSX 和现代 JavaScript 语法 &minu;

module.exports = {
  presets: [
    '@babel/preset-env',
    ['@babel/preset-react', { runtime: 'automatic' }]
  ]
};

5. 快照测试示例

Component: Link.tsx

import React from 'react';

interface LinkProps {
  page: string;
  children: React.ReactNode;
  status?: string;
}

const Link: React.FC<LinkProps> = ({ page, children, status }) => {
  return (
    <a className={status} href={page}>
      {children}
    </a>
  );
};

export default Link;

快照测试:Link.test.tsx

import React from 'react';
import renderer from 'react-test-renderer';
import Link from './Link';

describe('Link Component', () => {
  it('renders correctly with default props', () => {
    const tree = renderer
      .create(<Link page="https://example.com">Example</Link>)
      .toJSON();
    expect(tree).toMatchSnapshot();
  });

  it('applies status class when provided', () => {
    const tree = renderer
      .create(<Link page="https://example.com" status="active">Example</Link>)
      .toJSON();
    expect(tree).toMatchSnapshot();
  });
});

运行测试:使用以下命令运行测试

npm test

路由器

路由是在单页 React 应用程序中从一个视图或组件导航到另一个视图或组件的过程。这允许用户在不重新加载整个页面的情况下浏览应用程序。

要首先在应用程序中执行路由,我们需要安装 react-router −

npm install react-router-dom

1. 组件

About.jsx:

import React from 'react';
const About = () => {
  return (
    <>
      <h2>This is About ...</h2>
    </>
  );
};
export default About;

Home.jsx:

import React from 'react';

const Home = () => {
  return (
    <>
      <h2>Welcome to the Home Page ...</h2>
    </>
  );
};
export default Home;

2. 基本路由

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';

function App() {
  return (
    <>
      <Router>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
        </ul>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Router>
    </>
  );
}
export default App;

3. 精确路由

<Route exact path="/" element={<component_name/>} />

4. 带链接的导航

<Link to="/about">关于</Link>

5. 嵌套路由

import React from 'react';
import { Route, Link, useRouteMatch } from 'react-router-dom';

const Contacts = () => {
  const match = useRouteMatch();
  return <p>{match.params.id}</p>;
};

const Contact = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/contact/1">Contact 1</Link>
        </li>
      </ul>
      <Route path="/contact/:id" element={<Contacts/>} />
    </div>
  );
};

export default Contact;

Top-Level API

React Top-Level(顶级) API 包括可直接从"react"和"react-dom"包获取的关键组件、函数和实用程序。这些 API 允许开发人员有效地管理他们的 React 应用程序。

1. 组件

React.Component:它是用于创建基于类的组件的基类。

class MyComponent extends React.Component {
  render() {
    return <h1>Hello, Tutorialspoint!</h1>;
  }
}

React.PureComponent:它与 React.Component 类似,但它包含浅层 prop 和状态比较以提高性能。

class MyPureComponent extends React.PureComponent {
  render() {
    return <h1>{this.props.title}</h1>;
  }
}

1. 创建元素

React.createElement(type, [props], [...children]): JSX 内部使用它来创建 React 元素。

const element = React.createElement('h1', { className: 'greeting' }, 'Hello, World!');

React.cloneElement(element, [props], [...children]): 它用于克隆 React 元素,并可选择用于覆盖。

const newElement = React.cloneElement(existingElement, { className: 'new-class' });

React.isValidElement(element): 检查值是否为有效的 React 元素。

console.log(React.isValidElement(<h1>Hello</h1>));

2. Refs 和 Context

React.createRef(): 创建 refs 以访问 DOM 元素或类组件实例。

const inputRef = React.createRef();

React.createContext(defaultValue):它创建一个在 React 树中全局共享的上下文。

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

结论

正如我们介绍的,我们已经介绍了 React 的大部分核心功能和特性。此备忘录是您了解 React 中的概念、工具和 API 的完整指南。它是您提高对 React 的了解并明确您可以用它做什么和不能做什么的资源,包括其基于组件的架构、状态管理、Hooks(钩子)、上下文、路由和渲染策略方面的能力。