React.js 速查表 – 终极指南
React.js 是您设计动态、高效用户界面的首选。无论您是经验丰富的开发者还是 Web 开发新手,本博客都将讲解 React 组件、元素和关键概念。我们将帮助您掌握 JSX 语法、React 属性和条件语句。
React 速查表
React 是一个开源 JavaScript 库,用于以声明式和高效的方式构建用户界面。它采用基于组件的方法,专门在模型视图控制器 (MVC) 架构的视图层中运行。为了方便创建模块化用户界面,React 鼓励开发可重用的 UI 组件,这些组件能够通过 React 上下文呈现动态数据。
React 速查表是一份简明扼要的 React 常用方法参考资料。这份单页资源封装了关键组件和方法,方便用户轻松访问。让我们来看看一些 React 速查表:
React 元素
React 元素的语法与常规 HTML 元素相似。任何有效的 HTML 元素都可以用 React 来表达。
<h1>My Header</h1>
<p>My paragraph</p>
<button>My button</button>
这些 React 元素是使用 JSX 构建的,JSX 是 React 的一个独特功能,它将 HTML 语法与 JavaScript 函数融合在一起。
然而,由于 JSX 本质上是 JavaScript 函数(而不是 HTML),因此存在一些语法差异。值得注意的是,像 img 元素这样的单标签元素必须是自闭合的,并以正斜杠 / 结尾:
<img src="my-image.png" />
<br />
<hr />
React 元素属性
JSX 引入了新的属性语法,使其与 JavaScript 的驼峰命名约定保持一致。例如,HTML 中的 class 属性在 JSX 中变成了 className。
<div className="container"></div>
React 元素样式
在 JSX 中应用内联样式需要使用双花括号而不是双引号。样式不是以普通字符串的形式表示,而是以对象内的属性形式表示:
<h1 style={{ fontSize: 24, margin: '0 auto', textAlign: 'center' }}>My header</h1>
React 片段
React 提供了一个称为 fragment 的特殊元素,用于满足在单个父组件中返回所有元素的需求。这至关重要,因为 React 强制要求返回的元素只有一个“父级”。如果您不想使用像 div 这样的容器元素,可以使用 fragment:
// Valid syntax
function MyComponent() {
return (
<>
<h1>My header</h1>
<p>My paragraph</p>
</>
);
}
片段可以用常规或简写语法来编写:或 <></>。
React 组件
在 React useState Hook 领域,我们能够将元素集群组织成所谓的 React 组件。
基本函数组件的制作方式与标准 JavaScript 函数非常相似,但需要注意一些细微差别。
首先,组件名称必须以大写字母开头。也就是说,我们应该使用 MyComponent 而不是 myComponent。此外,与常规 JavaScript 函数不同,组件必须优雅地返回 JSX。
React 函数组件的基本语法如下:
function App() {
return (
<div>Hello world!</div>
);
}
React Props
在 React 的世界中,组件能够接收传递给它们的数据,我们将其称为 props。
这些 props 从父组件分发到子组件。举例来说,考虑将名为“name”的 prop 从 App 组件传递到 User 组件:
function App() {
return <User name="John Doe" />
}
function User(props) {
return <h1>Hello, {props.name}</h1>; // Hello, John Doe!
}
由于 props 本质上是一个对象,我们可以通过 react hooks 提取 User 组件内“name”prop 的值。
为了获得更清晰的代码方法,特别是在处理像“name”这样的单个 prop 时,可以采用对象解构:
function App() {
return <User name="John Doe" />
}
function User({ name }) {
return <h1>Hello, {name}!</h1>; // Hello, John Doe!
}
值得注意的是,任何 JavaScript 值(包括其他元素和组件)都可以作为 prop 传递。
React Children Props
也可以通过在组件的开始和结束标签之间放置数据来传递 props。以这种方式传递的 props 位于 children 的属性中。
例如,考虑在 User 组件的标签之间传递内容:
function App() {
return (
<User>
<h1>Hello, John Doe!</h1>
</User>
);
}
function User({ children }) {
return children; // Hello, John Doe!
}
React 条件语句
React 组件和元素可以有条件地显示。一种方法是使用单独的 return 语句和 if 语句。
function App() {
const isAuthUser = useAuth();
if (isAuthUser) {
// if our user is authenticated, let them use the app
return <AuthApp />;
}
// if user is not authenticated, show a different screen
return <UnAuthApp />;
}
如果您希望在返回语句中创建条件,则必须使用解析为值的条件。
要使用三元运算符,请将整个条件括在花括号中。
function App() {
const isAuthUser = useAuth();
return (
<>
<h1>My App</h1>
{isAuthUser ? <AuthApp /> : <UnAuthApp />}
</>
)
}
React 列表
可以使用 .map() 函数生成 React 组件列表,该函数允许我们遍历数据数组并生成 JSX。
考虑使用 SoccerPlayer 组件输出足球运动员列表的示例:
function SoccerPlayers() {
const players = ["Messi", "Ronaldo", "Laspada"];
return (
<div>
{players.map((playerName) => (
<SoccerPlayer key={playerName} name={playerName} />
))}
</div>
);
}
循环遍历数据数组时,必须包含 key 属性,并且必须为该键分配一个唯一值,而不仅仅是元素索引。在上面的例子中,playerName 这个唯一值充当了键。
反应上下文
React Context 作为一种机制,可在我们的组件树中无缝传递数据,从而无需完全依赖 props。
道具的挑战在于偶尔需要将它们传递到不一定需要数据的中间组件 - 这种问题通常称为道具钻探。
考虑这个简化的场景,其中 props 不必要地通过“Body”组件传递:
function App() {
return (
<Body name="John Doe" />
);
}
function Body({ name }) {
return (
<Greeting name={name} />
);
}
function Greeting({ name }) {
return <h1>Welcome, {name}</h1>;
}
在接受 Context 之前,值得探索的是我们的组件是否可以更好地构建以避免通过不必要的部分传递 props 的做法。
在实现 Context 时,我们使用 React 提供的 createContext 函数。调用此函数时,可以传入一个初始值,该初始值将成为 context 的起点。
生成的上下文包含一个 Provider 属性和一个 Consumer 属性,它们都充当组件的功能。Provider 属性包裹着需要传播数据的组件树,而 Consumer 属性则位于组件集内,用于消费该值。
import { createContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value="John Doe">
<Body />
</NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
return (
<NameContext.Consumer>
{name => <h1>Welcome, {name}</h1>}
</NameContext.Consumer>
);
}
通过采用这种方法,我们增强了组件的组织性,并避免了通过组件树中多余的元素传递 props 的需要。
React Hooks
React Hooks 随着 React 16.8 版本出现,提供了一种将可重用、有状态的逻辑集成到 React 函数组件中的便捷方法,从而将其功能扩展到传统类组件所独有的功能之外。
这些钩子使我们能够利用以前为类组件保留的功能,甚至可以定制自己的钩子,以赋予应用程序特定的功能。React 库包含许多重要的钩子,我们将深入探讨其中六个对您理解至关重要的钩子:
- useState
- useEffect
- useRef
- useContext
- 使用回调
- 使用备忘录
useState 钩子尤其名副其实,它允许我们在函数组件中使用状态值。相比简单的变量,useState 钩子更受欢迎,因为当状态修改时,组件会自动重新渲染以反映更新后的值。
使用 useState 时,我们在组件顶部初始化它,并可选地为其状态变量传递一个初始值。对返回值进行数组解构,使我们能够访问存储的状态以及用于更新该状态的函数。
import { useState } from 'react';
function MyComponent() {
const [stateValue, setStateValue] = useState(initialValue);
}
A practical illustration involves a basic counter that increments upon interaction:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={updateCount}>Count is: {count}</button>;
}
这展示了 useState 如何以功能性和直接的方式促进状态管理,丰富了 React 函数组件的功能。
React useState 钩子
React useState 钩子的用途很简单——它支持在函数组件中使用状态值。
之所以使用 useState 而不是依赖基本变量,是因为在修改状态后,我们的组件会重新渲染,通常是为了展示更新的值。
为了与其他钩子的模式保持一致,我们在组件开始时调用 useState,从而允许我们提供填充其状态变量的初始值。
对 useState 返回的值使用数组解构使我们能够方便地访问存储的状态和专用于更新该状态的函数。
import { useState } from 'react';
function MyComponent() {
const [stateValue, setStateValue] = useState(initialValue);
}
For a practical demonstration, let’s consider a basic example involving the incrementation of a counter.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={updateCount}>Count is: {count}</button>;
}
这展示了 useState hook 如何简化函数组件中的状态管理。通过提供无缝处理状态变化的方式,它增强了 React 组件的功能,正如这个简单的计数器场景所示。
使用现成的React Admin 模板简化您的开发流程。
React useEffect 钩子
当我们需要与外部环境交互(例如进行 API 调用)时,React 的 useEffect hook 就会发挥作用。它的主要目的是处理副作用,包括应用程序之外的、结果不可预测的操作。
useEffect 的基本语法包括提供一个函数作为第一个参数和一个数组作为第二个参数。
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// Perform side effect here
}, []);
}
为了说明其在获取和显示帖子列表方面的用法,请考虑以下示例:
import { useEffect } from 'react';
function PostList() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(posts => setPosts(posts));
}, []);
return posts.map(post => <Post key={post.id} post={post} />);
}
如果我们需要从 effect 函数外部获取值,则必须将其包含在依赖项数组中。如果该值发生变化,effect 函数将重新执行。
作为说明,请考虑以下代码片段,该代码片段根据移动菜单是打开还是关闭来切换 body 元素上的“overflow-hidden”类:
function Mobile({ open }) {
useEffect(() => {
const body = document.querySelector("#__next");
if (open) {
body.classList.add("overflow-hidden");
} else {
body.classList.remove("overflow-hidden");
}
}, [open]);
// ...
}
这体现了 useEffect 如何有效地管理副作用,确保我们与外部世界的交互无缝集成到 React 组件生命周期中。
React useRef
React useRef 钩子提供了到 JSX 元素的直接网关,提供了一种无需 prop 钻取即可访问它的机制。
要使用 useRef,只需调用 hook,检索返回值,并将其赋值给所需 React 元素的 ref prop。需要注意的是,refs 不是组件的固有属性,而是 React 元素的固有属性。
useRef 的基本语法如下:
import { useRef } from 'react';
function MyComponent() {
const ref = useRef();
return <div ref={ref} />;
}
一旦 ref 链接到特定元素,就可以利用 ref.current 中存储的值直接与底层元素进行交互。例如,假设我们希望在用户使用组合键 Control + K 时将焦点集中在搜索输入上:
import { useWindowEvent } from "@mantine/hooks";
import { useRef } from "react";
function Header() {
const inputRef = useRef();
useWindowEvent("keydown", (event) => {
if (event.code === "KeyK" && event.ctrlKey) {
event.preventDefault();
inputRef.current.focus();
}
});
return <input ref={inputRef} />;
}
在这个场景中,inputRef 用于直接访问输入元素,展示了 useRef 如何增强我们与 React 组件中特定元素交互的能力。
React useContext
与使用标准 Context.Consumer 组件相比,React useContext 钩子简化了上下文的使用。
该语法需要将我们想要使用的整个 Context 对象传递给 useContext。返回的值对应于通过 Context 传播的值。
import { useContext } from 'react';
function MyComponent() {
const value = useContext(Context);
// ...
}
To adapt our previous example using the useContext hook:
import { createContext, useContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value="John Doe">
<Body />
</NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
const name = useContext(NameContext);
return (
<h1>Welcome, {name}</h1>
);
}
这展示了 useContext 如何简化访问上下文值的过程,与传统的 Context.Consumer 组件相比,它提供了更简洁、更易读的方法。
React useCallback
React 的 useCallback 钩子是一个很有价值的工具,它可以防止组件每次重新渲染时重新创建函数,从而优化应用程序的性能。这对于保持应用程序的效率至关重要。
为了说明这一点,请考虑我们之前使用 PlayerList 的示例。如果我们对其进行增强,允许将玩家添加到数组中,并通过 props 传递一个函数 (handleRemovePlayer) 来移除玩家,那么每次重新渲染时都会重新创建该函数,这可能会影响性能。
为了解决这个问题,我们可以使用 useCallback 来封装回调函数,并将其唯一参数 player 包含在依赖项数组中。以下是人工编写的代码版本:
function App() {
const [player, setPlayer] = React.useState("");
const [players, setPlayers] = React.useState(["Messi", "Ronaldo", "Laspada"]);
function handleChangeInput(event) {
setPlayer(event.target.value);
}
function handleAddPlayer() {
setPlayers(players.concat(player));
}
const handleRemovePlayer = useCallback((player) => {
setPlayers(players.filter((p) => p !== player));
}, [players]);
return (
<>
<input onChange={handleChangeInput} />
<button onClick={handleAddPlayer}>Add Player</button>
<PlayerList players={players} handleRemovePlayer={handleRemovePlayer} />
</>
);
}
function PlayerList({ players, handleRemovePlayer }) {
return (
<ul>
{players.map((player) => (
<li key={player} onClick={() => handleRemovePlayer(player)}>
{player}
</li>
))}
</ul>
);
}
React useMemo
继续使用 useMemo,这个性能增强钩子允许我们“记忆”操作,记住昂贵计算的结果,以避免不必要的重新计算。
与 useEffect 和 useCallback 不同,useMemo 旨在返回一个值。它需要一个回调函数和一个依赖项数组,并且回调必须显式返回该值。让我们考虑一个来自 mdx-bundler 文档的实际示例,它将 .mdx 文件转换为 React 组件:
import * as React from 'react';
import { getMDXComponent } from 'mdx-bundler/client';
function Post({ code, frontmatter }) {
const Component = React.useMemo(() => getMDXComponent(code), [code]);
return (
<>
<header>
<h1>{frontmatter.title}</h1>
<p>{frontmatter.description}</p>
</header>
<main>
<Component />
</main>
</>
);
}
在这里,useMemo 确保在重新渲染期间不会不必要地重新创建组件值,从而提高性能。
关注我们-
https://twitter.com/codedthemes/
https://www.facebook.com/codedthemes/
https://in.linkedin.com/company/codedthemes
https://www.instagram.com/codedthemes/