react 知识点汇总(非常全面)
<p>React 是一个用于构建用户界面的 JavaScript 库,由 Facebook 开发并维护。它的核心理念是“组件化”,即将用户界面拆分为可重用的组件。</p><p>React 的组件通常使用 JSX(JavaScript XML)。JSX 是一种 JavaScript 语法扩展,允许开发者在 JavaScript 代码中编写类似 HTML 的结构。</p>
<h2 id="1初识react">1、初识react</h2>
<h3 id="11-常用命令">1.1 常用命令</h3>
<p>首先安装Nodejs,然后执行下面命令安装 <code>react</code></p>
<pre><code class="language-bash">npm i -g create-react-app
</code></pre>
<pre><code class="language-bash">create-react-app myreact # 创建react项目
npm start # 在项目中输入,启动项目
</code></pre>
<h3 id="12-项目结构">1.2 项目结构</h3>
<p>项目创建后有很多文件,一般我们只需保留下面的就行.</p>
<ul>
<li><strong><code>index.html</code></strong>:应用的主 HTML 文件,React 应用的根组件通常挂载在此文件中的一个 <div> 元素上。</div></li>
<li><strong><code>index.css</code></strong>:全局样式文件。</li>
<li><strong><code>index.js</code></strong>:应用的入口文件,负责渲染根组件并将其挂载到 <code>index.html</code> 中的 DOM。</li>
<li><strong><code>package.json</code></strong>: 包含项目的元数据(如名称、版本、描述等)、依赖包列表和脚本命令(如 <code>start</code>、<code>build</code>、<code>test</code>)。</li>
</ul>
<pre><code class="language-html">my-app/
├── node_modules/
├── public/
│ ├── favicon.ico
| ├── index.html
├── src/
│ ├── index.css
│ ├── index.js
├── .gitignore
├── package.json
├── README.md
└── yarn.lock / package-lock.json
</code></pre>
<h2 id="2基本知识点">2、基本知识点</h2>
<h3 id="1-extends-component">1. <code>extends Component</code></h3>
<p>在 React 中,<code>extends Component</code> 是用来创建类组件的方式。React 的类组件通过继承 <code>React.Component</code> 来获得组件的基本功能,如状态管理和生命周期方法。以下是一个简单的例子:</p>
<pre><code class="language-javascript">import React, { Component } from 'react';
class MyComponent extends Component {
render() {
return <h1>Hello, World!</h1>;
}
}
</code></pre>
<ul>
<li>
<p><strong><code>Component</code></strong>:是 React 提供的基类,包含了生命周期方法(如 <code>componentDidMount</code>、<code>componentDidUpdate</code> 等)和其他基本功能。</p>
</li>
<li>
<p><strong><code>render</code> 方法</strong>:每个类组件必须实现的一个方法,用于描述 UI 如何渲染。每当组件的 <code>state</code> 或 <code>props</code> 更新时,<code>render</code> 方法会被调用。</p>
<pre><code class="language-javascript">render() {
return (
<div>
<h1>Hello, {this.props.name}!</h1>
</div>
);
}
</code></pre>
<ul>
<li><strong>返回值</strong>:<code>render</code> 方法可以返回一个单一的元素、多个元素(需要用一个父元素包裹)或者 <code>null</code>。</li>
</ul>
</li>
</ul>
<h3 id="2-reactfragment">2. <code>React.Fragment</code></h3>
<p><code>React.Fragment</code> 是一个用于分组多个子元素而不添加额外 DOM 节点的工具。通常,React 要求每个组件必须返回一个单一的根元素,使用 <code>Fragment</code> 可以解决这个问题。示例:</p>
<pre><code class="language-javascript">import React from 'react';
class MyComponent extends Component {
render() {
return (
<React.Fragment>
<h1>Title</h1>
<p>Some content.</p>
</React.Fragment>
);
}
}
</code></pre>
<ul>
<li><strong>语法简化</strong>:可以用 <code><></code> 和 <code></></code> 来简化 <code>Fragment</code> 的使用:</li>
</ul>
<h3 id="3-classname">3. <code>className</code></h3>
<p>在 React 中,使用 <code>className</code> 属性来指定一个或多个 CSS 类,而不是使用 HTML 的 <code>class</code> 属性。这是因为 <code>class</code> 是 JavaScript 中的保留关键字,React 采用 <code>className</code> 来避免冲突。</p>
<p><strong>示例:</strong></p>
<pre><code class="language-javascript">function MyComponent() {
return <div className="my-class">Hello, World!</div>;
}
</code></pre>
<pre><code class="language-css">.my-class {
color: blue;
font-size: 20px;
}
</code></pre>
<h4 id="动态类名">动态类名</h4>
<pre><code class="language-javascript">function MyComponent({ isActive }) {
return (
<div className={`my-class ${isActive ? 'active' : ''}`}>
Hello, World!
</div>
);
}
</code></pre>
<p>在这个例子中,如果 <code>isActive</code> 为 <code>true</code>,<code>div</code> 将具有 <code>active</code> 类。</p>
<h3 id="4--的用法">4. <code>{}</code> 的用法</h3>
<p>在 JSX 中,<code>{}</code> 用于表示 JavaScript 表达式。你可以在其中嵌入变量、函数调用和其他表达式。</p>
<p><strong>示例:</strong></p>
<pre><code class="language-javascript">const name = "Alice";
function Greeting() {
return <h1>Hello, {name}!</h1>; // 使用 {} 插入变量
}
</code></pre>
<h3 id="5-jsx-中的-css">5 jsx 中的 css</h3>
<h4 id="1-基本语法">1. 基本语法</h4>
<p>在 JSX 中,内联样式需要使用 JavaScript 对象的形式定义。具体来说:</p>
<ul>
<li>样式属性使用驼峰命名法(camelCase)。</li>
<li>属性值通常为字符串或数字(需要附加单位时,使用字符串)。</li>
</ul>
<h4 id="11-示例代码">1.1 示例代码</h4>
<pre><code class="language-javascript">const MyComponent = () => {
const style = {
color: 'blue',
backgroundColor: 'lightgray',
padding: '10px',
fontSize: '16px',
border: '1px solid black'
};
return <div style={style}>这是一个内联样式的组件</div>;
};
</code></pre>
<p>在这个示例中,我们定义了一个样式对象 <code>style</code>,并将其应用到 <code><div></code> 元素中。</p>
<h4 id="2-动态样式">2. 动态样式</h4>
<p>内联样式的一个主要优势是可以很容易地根据组件的状态或属性动态更新样式。例如,可以根据 <code>state</code> 的值来改变样式:</p>
<pre><code class="language-javascript">import React, { useState } from 'react';
const DynamicStyleComponent = () => {
const = useState(false);
const style = {
color: isActive ? 'white' : 'black',
backgroundColor: isActive ? 'blue' : 'gray',
padding: '10px',
cursor: 'pointer'
};
return (
<div
style={style}
onClick={() => setIsActive(!isActive)}
>
{isActive ? '激活状态' : '非激活状态'}
</div>
);
};
</code></pre>
<p>在这个示例中,点击 <code><div></code> 会切换其状态,从而改变文字和背景颜色。</p>
<h4 id="3-优缺点">3. 优缺点</h4>
<h5 id="优点">优点</h5>
<ul>
<li><strong>简单直接</strong>:可以快速应用样式,尤其是动态样式时。</li>
<li><strong>无类名冲突</strong>:因为样式是局部的,不会受到其他样式的影响。</li>
</ul>
<h5 id="缺点">缺点</h5>
<ul>
<li><strong>不可复用</strong>:无法将样式应用于多个组件,难以维护。</li>
<li><strong>性能问题</strong>:每次渲染都会创建新的对象,可能会影响性能,特别是在频繁更新的组件中。</li>
<li><strong>不支持伪类和媒体查询</strong>:无法使用 CSS 的伪类(如 <code>:hover</code>)和媒体查询,限制了样式的灵活性。</li>
</ul>
<h2 id="3componets-写法">3、Componets 写法</h2>
<h3 id="1-react-组件的基本概念">1. React 组件的基本概念</h3>
<p>React 组件是构成 React 应用的基本单元。它们可以是类组件或函数组件。类组件使用 ES6 类来定义,而函数组件则是简单的 JavaScript 函数。</p>
<h4 id="11-类组件">1.1 类组件</h4>
<p>类组件通常用于需要管理状态或使用生命周期方法的场景。</p>
<pre><code class="language-javascript">import React, { Component } from 'react';
class MyComponent extends Component {
// 构造函数用于初始化 state
constructor(props) {
super(props);
this.state = {
count: 0
};
}
// 上面 constructor 这块的代码可以只写 state {count : 0},
// 在类组件中,可以直接在类的主体中定义 state,而不必在构造函数中初始化。
// 这种语法会自动将 state 绑定到实例上,因此不需要显式调用 super(props)。
// 增加 count 的方法
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.increment}>增加</button>
</div>
);
}
}
export default MyComponent;
</code></pre>
<h4 id="12-函数组件">1.2 函数组件</h4>
<p>函数组件是无状态的,可以使用 React Hooks 来管理状态和副作用。</p>
<pre><code class="language-javascript">import React, { useState } from 'react';
const MyComponent = () => {
const = useState(0); // useState Hook
const increment = () => {
setCount(count + 1);
};
return (
<div>
<h1>{count}</h1>
<button onClick={increment}>增加</button>
</div>
);
};
export default MyComponent;
</code></pre>
<h3 id="2-state-的管理">2. State 的管理</h3>
<p><code>state</code> 是组件的本地状态,用于存储组件的动态数据。当状态改变时,React 会自动重新渲染组件。</p>
<h4 id="21-设置初始状态">2.1 设置初始状态</h4>
<p>在类组件中,初始状态通常在构造函数中定义;在函数组件中,可以使用 <code>useState</code> Hook。</p>
<h4 id="22-修改状态">2.2 修改状态</h4>
<p>使用 <code>this.setState</code>(类组件)或状态更新函数(函数组件)来更新状态。重要的是,状态更新是异步的。</p>
<pre><code class="language-javascript">// 类组件
this.setState({ key: value });
// 函数组件
setCount(newCount);
</code></pre>
<h3 id="3-遍历生成元素">3. 遍历生成元素</h3>
<p>在状态中存储一个数组,然后通过 <code>.map()</code> 方法遍历生成多个元素。</p>
<h4 id="31-类组件示例">3.1 类组件示例</h4>
<pre><code class="language-javascript">class ListComponent extends Component {
constructor(props) {
super(props);
this.state = {
items: ['苹果', '香蕉', '橙子']
};
}
render() {
return (
<ul>
{this.state.items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
}
</code></pre>
<h4 id="32-函数组件示例">3.2 函数组件示例</h4>
<pre><code class="language-javascript">const ListComponent = () => {
const = useState(['苹果', '香蕉', '橙子']);
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
</code></pre>
<h3 id="4-函数传参">4. 函数传参</h3>
<h4 id="41-传递参数-e">4.1 传递参数 e</h4>
<pre><code class="language-js">class MyComponent extends Component {
handleClick = (e) => {
console.log(e.target);
};
render() {
return (
<button onClick={this.handleClick}> // 传递参数 e
Click me
</button>
);
}
}
</code></pre>
<h4 id="42-传递自定义参数">4.2 传递自定义参数</h4>
<pre><code class="language-js">class MyComponent extends Component {
handleClick = (param) => {
console.log('Button clicked!', param);
};
render() {
return (
<button onClick={() => this.handleClick('Hello')}> // 传递自定义参数
Click me
</button>
);
}
}
</code></pre>
<h4 id="43-传递参数-e-和-自定义参数">4.3 传递参数 e 和 自定义参数</h4>
<pre><code class="language-js">class MyComponent extends Component {
handleClick = (param, e) => {
console.log('Button clicked!', param);
};
render() {
return (
<button onClick={(e) => this.handleClick('Hello', e)}> // 传递参数
Click me
</button>
);
}
}
</code></pre>
<h3 id="5-添加删除和更新状态">5. 添加、删除和更新状态</h3>
<p>可以通过按钮或其他交互方式来添加、删除或更新状态中的元素。</p>
<h4 id="51-添加元素">5.1 添加元素</h4>
<pre><code class="language-javascript">// 在类组件中
addItem = () => {
this.setState(prevState => ({
items: [...prevState.items, '新水果']
}));
};
// 在函数组件中
const addItem = () => {
setItems([...items, '新水果']);
};
</code></pre>
<h4 id="52-删除元素">5.2 删除元素</h4>
<pre><code class="language-javascript">// 在类组件中
removeItem = index => {
this.setState(prevState => ({
items: prevState.items.filter((_, i) => i !== index)
}));
};
// 在函数组件中
const removeItem = index => {
setItems(items.filter((_, i) => i !== index));
};
</code></pre>
<h3 id="6-受控表单绑定">6. 受控表单绑定</h3>
<pre><code class="language-javascript">import React, { useState } from 'react';
function ControlledForm() {
const = useState('');
const = useState('');
const handleSubmit = (e) => {
e.preventDefault();
alert(`Name: ${name}, Email: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Name:
<input
type="text"
value={name} // 把 name 赋值给value
onChange={(e) => setName(e.target.value)} // name 绑定上target.value
/>
</label>
</div>
<div>
<label>
Email:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default ControlledForm;
</code></pre>
<h3 id="7-获取dom元素">7. 获取dom元素</h3>
<h4 id="1-函数组件">1. 函数组件</h4>
<p>可以通过 <code>useRef</code> 创建 refs:</p>
<pre><code class="language-javascript">import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus(); // 获取到的 DOM 元素调用 focus 方法
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleFocus}>Focus the input</button>
</div>
);
}
export default FocusInput;
</code></pre>
<ul>
<li><strong><code>useRef</code></strong>: 创建一个 <code>ref</code>,用于存储对 DOM 元素的引用。</li>
<li><strong><code>ref</code> 属性</strong>: 将 <code>ref</code> 赋值给要获取的元素,例如 <code><input></code>。</li>
<li><strong>访问 DOM 元素</strong>: 通过 <code>inputRef.current</code> 来访问 DOM 元素。</li>
</ul>
<h4 id="2-类组件">2. 类组件</h4>
<p>可以通过 <code>React.createRef()</code> 创建 refs:</p>
<pre><code class="language-javascript">import React, { Component } from 'react';
class FocusInput extends Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
handleFocus = () => {
this.inputRef.current.focus();
};
render() {
return (
<div>
<input type="text" ref={this.inputRef} />
<button onClick={this.handleFocus}>Focus the input</button>
</div>
);
}
}
export default FocusInput;
</code></pre>
<h2 id="4组件之间传递数据">4、组件之间传递数据</h2>
<p>子组件接收到的 props 是不可变的。如果需要修改 props 中的数据,应该通过父组件来管理状态并传递更新的值。</p>
<p><code>1 - 4</code> 都是 父传子, <code>5</code> 是 子传父</p>
<h3 id="1-传递常见数据类型类组件写法">1. 传递常见数据类型(类组件写法)</h3>
<p>在父组件的 <code>state</code> 中存储基本数据类型,并通过 <code>props</code> 传递给子组件。</p>
<p><strong>父组件</strong></p>
<pre><code class="language-js">import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends Component {
state = {
// 基本数据类型
message: 'Hello from Parent!',
numberValue: 42,
boolValue: true,
user: { // 对象
name: 'Alice',
age: 30,
},
};
handleAlert = () => { // 方法
alert('Hello from Parent!');
};
updateBoolValue = () => {
this.setState(prevState => ({ boolValue: !prevState.boolValue }));
};
render() {
return (
<div>
<h1>Parent Component</h1>
<ChildComponent
message={this.state.message}
number={this.state.numberValue}
isTrue={this.state.boolValue}
user={this.state.user} // 对象
showAlert={this.handleAlert} // 方法
/>
<button onClick={this.updateBoolValue}>Toggle Boolean</button>
</div>
);
}
}
export default ParentComponent;
</code></pre>
<p><strong>子组件</strong></p>
<pre><code class="language-js">import React, { Component } from 'react';
class ChildComponent extends Component {
render() {
return (
<div>
<h2>Child Component</h2>
<p>{this.props.message}</p>
<p>Number: {this.props.number}</p>
<p>Boolean: {this.props.isTrue ? 'True' : 'False'}</p>
<ChildComponent user={this.state.user} /> // 对象
</div>
);
}
}
export default ChildComponent;
</code></pre>
<h3 id="2-传递常见数据类型函数组件写法">2. 传递常见数据类型(函数组件写法)</h3>
<p><strong>父组件</strong></p>
<pre><code class="language-javascript">import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const = useState('Hello from Parent!');
const = useState(42);
const = useState(true);
const = useState({
name: 'Alice',
age: 30,
});
const handleAlert = () => {
alert('Hello from Parent!');
};
const updateBoolValue = () => {
setBoolValue(prev => !prev);
};
return (
<div>
<h1>Parent Component</h1>
<ChildComponent
message={message}
number={numberValue}
isTrue={boolValue}
user={user}
showAlert={handleAlert}
/>
<button onClick={updateBoolValue}>Toggle Boolean</button>
</div>
);
};
export default ParentComponent;
</code></pre>
<p><strong>子组件</strong></p>
<pre><code class="language-javascript">import React from 'react';
const ChildComponent = ({ message, number, isTrue, user }) => {
return (
<div>
<h2>Child Component</h2>
<p>{message}</p>
<p>Number: {number}</p>
<p>Boolean: {isTrue ? 'True' : 'False'}</p>
<p>User: {user.name}, Age: {user.age}</p> {/* 对象 */}
</div>
);
};
export default ChildComponent;
</code></pre>
<p>说明</p>
<ul>
<li>使用 <code>useState</code> 来管理状态。</li>
<li>通过解构 props 直接在函数参数中获取需要的值。</li>
<li>保持功能和逻辑不变,实现了相同的父子组件传值。</li>
</ul>
<h3 id="3-传递多个-html-结构类组件">3. 传递多个 HTML 结构(类组件)</h3>
<p>父组件将多个 JSX 元素传递给子组件,通过 <code>props.children</code> 访问这些元素。</p>
<pre><code class="language-js">import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends Component {
render() {
return (
<div>
<h1>Parent Component</h1>
<ChildComponent> //把 html 写在组件子组件当中
<p>This is the first custom content!</p>
<p>This is the second custom content!</p>
<h3>This is a header as custom content!</h3>
</ChildComponent>
</div>
);
}
}
export default ParentComponent;
</code></pre>
<p><strong>子组件</strong></p>
<p>在子组件中,我们可以通过 <code>React.Children.map</code> 或者 <code>this.props.children</code> 分别处理传递过来的多个元素。</p>
<pre><code class="language-js">import React, { Component } from 'react';
class ChildComponent extends Component {
render() {
return (
<div>
<h2>Child Component</h2> // children数组中包含了父组件传递的 html
{React.Children.map(this.props.children, (child, index) => (
<div key={index}>{child}</div>
))}
</div>
);
}
}
export default ChildComponent;
</code></pre>
<h3 id="4-传递多个-html-结构函数组件">4. 传递多个 HTML 结构(函数组件)</h3>
<p><strong>父组件</strong></p>
<pre><code class="language-javascript">import React from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
return (
<div>
<h1>Parent Component</h1>
<ChildComponent>
<p>This is the first custom content!</p>
<p>This is the second custom content!</p>
<h3>This is a header as custom content!</h3>
</ChildComponent>
</div>
);
};
export default ParentComponent;
</code></pre>
<p><strong>子组件</strong></p>
<pre><code class="language-javascript">import React from 'react';
const ChildComponent = ({ children }) => {
return (
<div>
<h2>Child Component</h2>
{React.Children.map(children, (child, index) => (
<div key={index}>{child}</div>
))}
</div>
);
};
export default ChildComponent;
</code></pre>
<p>说明</p>
<ul>
<li><strong>父组件</strong>: 使用函数组件,并将多个 JSX 元素作为子组件的内容传递。</li>
<li><strong>子组件</strong>: 通过解构 props 获取 <code>children</code>,并使用 <code>React.Children.map</code> 迭代处理每个子元素。</li>
</ul>
<h3 id="5-子传父">5. 子传父</h3>
<p><strong>父组件</strong></p>
<pre><code class="language-javascript">import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const = useState('');
const handleDataChange = (data) => {
setDataFromChild(data);
};
return (
<div>
<h1>Parent Component</h1>
<p>Data from Child: {dataFromChild}</p>
<ChildComponent onDataChange={handleDataChange} />
</div>
);
};
export default ParentComponent;
</code></pre>
<p><strong>子组件</strong></p>
<pre><code class="language-javascript">import React from 'react';
const ChildComponent = ({ onDataChange }) => {
const sendDataToParent = () => {
const data = 'Hello from Child!';
onDataChange(data); // 调用父组件传来的函数
};
return (
<div>
<h2>Child Component</h2>
<button onClick={sendDataToParent}>Send Data to Parent</button>
</div>
);
};
export default ChildComponent;
</code></pre>
<p>说明</p>
<ol>
<li><strong>父组件</strong>: <code>ParentComponent</code> 使用 <code>useState</code> 来存储从子组件接收到的数据,并定义一个 <code>handleDataChange</code> 函数来更新状态。</li>
<li><strong>子组件</strong>: <code>ChildComponent</code> 接收 <code>onDataChange</code> 函数作为 prop,点击按钮时调用该函数将数据发送给父组件。</li>
</ol>
<h2 id="5生命周期">5、生命周期</h2>
<ul>
<li>
<p><strong>挂载阶段</strong>:</p>
<ul>
<li><code>constructor()</code></li>
<li><code>render()</code></li>
<li><code>componentDidMount()</code></li>
</ul>
</li>
<li>
<p><strong>更新阶段</strong>:</p>
<ul>
<li><code>getDerivedStateFromProps()</code></li>
<li><code>shouldComponentUpdate()</code></li>
<li><code>render()</code></li>
<li><code>componentDidUpdate()</code></li>
</ul>
</li>
<li>
<p><strong>卸载阶段</strong>:</p>
<ul>
<li><code>componentWillUnmount()</code></li>
</ul>
</li>
</ul>
<h3 id="1-挂载mount">1. 挂载(Mount)</h3>
<p>当组件被创建并插入到 DOM 中时,进入挂载阶段。执行顺序如下:</p>
<ol>
<li><strong>constructor()</strong>:构造函数用于初始化状态和绑定方法。</li>
<li><strong>render()</strong>:返回要渲染的 JSX,决定组件的结构。</li>
<li><strong>componentDidMount()</strong>:组件挂载后调用,适合进行 API 请求或添加事件监听。</li>
</ol>
<h3 id="2-更新update">2. 更新(Update)</h3>
<p>当组件的状态或属性发生变化时,组件会重新渲染,进入更新阶段。执行顺序如下:</p>
<ol>
<li><strong>render()</strong>:重新渲染组件。</li>
<li><strong>getDerivedStateFromProps(nextProps, prevState)</strong>:在渲染前调用,可以根据新 props 更新 state。</li>
<li><strong>shouldComponentUpdate(nextProps, nextState)</strong>:用于控制组件是否重新渲染,返回 <code>true</code> 或 <code>false</code>。</li>
<li><strong>componentDidUpdate(prevProps, prevState)</strong>:组件更新后调用,可以根据上一个状态或属性执行副作用。</li>
</ol>
<h3 id="3-卸载unmount">3. 卸载(Unmount)</h3>
<p>当组件从 DOM 中移除时,进入卸载阶段。执行顺序如下:</p>
<ol>
<li><strong>componentWillUnmount()</strong>:组件卸载前调用,适合清理资源(如取消网络请求或移除事件监听)。</li>
</ol>
<h3 id="4-使用-hook-的方式">4. 使用 Hook 的方式</h3>
<p>在函数组件中,可以使用 Hook 来实现类似的生命周期效果:</p>
<ul>
<li><strong>useEffect</strong>:相当于 <code>componentDidMount</code> 和 <code>componentDidUpdate</code>,可以用于处理副作用。</li>
</ul>
<pre><code class="language-jsx">import React, { useEffect, useState } from 'react';
const MyComponent = () => {
const = useState(0);
useEffect(() => {
// 组件挂载时执行
console.log('Component mounted');
// 组件更新时执行
return () => {
// 组件卸载时清理
console.log('Component unmounted');
};
}, ); // 依赖数组,count 变化时执行
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
</code></pre>
<h2 id="6-路由">6、 路由</h2>
<h3 id="1-基础概念">1. 基础概念</h3>
<p><strong>路由(Routing)</strong>:在单页应用(SPA)中,路由用于管理不同视图或页面之间的导航。当用户点击链接或按钮时,路由会拦截这些操作,并根据 URL 的变化加载相应的组件,而不需要重新加载整个页面。</p>
<p><strong>React Router</strong>:这是最流行的 React 路由库,它提供了灵活的路由功能。React Router 通过组件化的方式来定义和管理路由。</p>
<h3 id="2-常用组件">2. 常用组件</h3>
<p>React Router 提供了几个核心组件,下面是一些常用的组件及其用途:</p>
<ul>
<li>
<p><strong>BrowserRouter</strong>:这个组件提供了基于 HTML5 的历史记录的路由。它通常包裹在应用的根组件外部。</p>
<pre><code class="language-js">import { BrowserRouter } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
{/* 其他组件 */}
</BrowserRouter>
);
}
</code></pre>
</li>
<li>
<p><strong>Route</strong>:用于定义路由的组件。它接受 <code>path</code> 属性来指定匹配的 URL,以及 <code>element</code> 属性来指定渲染的组件。</p>
<pre><code class="language-js">import { Route } from 'react-router-dom';
<Route path="/about" element={<About />} />
</code></pre>
</li>
<li>
<p><strong>Routes</strong>:用来包裹多个 Route 组件,确保只有一个匹配的路由被渲染。</p>
<pre><code class="language-js">import { Routes } from 'react-router-dom';
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</code></pre>
</li>
<li>
<p><strong>Link</strong>:用于在应用中创建导航链接的组件。它类似于 HTML 的 <code><a></code> 标签,但使用的是客户端路由。</p>
<pre><code class="language-js">import { Link } from 'react-router-dom';
<Link to="/about">About</Link>
</code></pre>
</li>
<li>
<p><strong>Navigate</strong>:用于在组件中进行重定向。</p>
<pre><code class="language-jsx">import { Navigate } from 'react-router-dom';
<Navigate to="/home" />
</code></pre>
</li>
</ul>
<h3 id="3-路由配置">3. 路由配置</h3>
<p>配置路由通常涉及创建一个路由表,定义各个路由及其对应的组件。以下是一个简单的示例,展示如何在 React 应用中配置路由。</p>
<pre><code class="language-js">import React from 'react';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
// 导入页面组件
import Home from './Home';
import About from './About';
import NotFound from './NotFound';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* 404 页面 */}
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
export default App;
</code></pre>
<h3 id="4-嵌套路由-及-路由守卫404">4. 嵌套路由 及 路由守卫、404</h3>
<p>嵌套路由允许你在某个父路由的组件内部定义子路由。这样,你可以在父路由的页面中渲染子路由对应的内容。</p>
<pre><code class="language-js">import { Routes, Route, Link } from 'react-router-dom';
function Users() {
return (
<div>
<h2>Users</h2>
<Link to="1">User 1</Link>
<Link to="2">User 2</Link>
<Routes>
<Route path=":userId" element={<UserProfile />} />
</Routes>
</div>
);
}
function UserProfile() {
const { userId } = useParams();
return <h3>User Profile for User ID: {userId}</h3>;
}
</code></pre>
<p><strong>路由守卫</strong></p>
<p>路由保护可以确保只有特定条件下(例如用户登录后)才能访问某些路由。可以通过创建一个高阶组件(HOC)来实现。</p>
<pre><code class="language-js">function ProtectedRoute({ element, isAuthenticated }) {
return isAuthenticated ? element : <Navigate to="/login" />;
}
// 使用
<Routes>
<Route path="/dashboard" element={<ProtectedRoute element={<Dashboard />} isAuthenticated={isLoggedIn} />} />
</Routes>
</code></pre>
<p><strong>404 页面处理</strong></p>
<p>可以使用通配符路由 <code>*</code> 来处理未匹配的路径,并显示 404 页面。</p>
<pre><code class="language-js"><Route path="*" element={<NotFound />} />
</code></pre>
<h3 id="5-动态路由match">5. 动态路由(match)</h3>
<p>动态路由允许你在路径中使用参数,这样可以在 URL 中捕获动态值。例如,展示用户信息的页面。</p>
<pre><code class="language-js"><Route path="/users/:userId" element={<UserProfile />} />
</code></pre>
<h4 id="类组件中">类组件中</h4>
<p>使用 URL 参数,可以使用 <code>withRouter</code> 高阶组件来获取路由的 props,包括 <code>match</code>、<code>location</code> 和 <code>history</code> 对象。</p>
<p><strong>使用 <code>withRouter</code> 获取 URL 参数</strong></p>
<pre><code class="language-js">import React from 'react';
import { withRouter } from 'react-router-dom';
class UserProfile extends React.Component {
render() {
// 从 props 中获取 match 对象
const { match } = this.props;
const userId = match.params.userId; // 获取 URL 参数
return <div>User ID: {userId}</div>;
}
}
// 使用 withRouter 将 UserProfile 包装起来
export default withRouter(UserProfile);
</code></pre>
<p><strong>关键点</strong></p>
<ul>
<li><code>withRouter</code> 是一个高阶组件,它将路由的相关信息作为 props 传递给被包装的组件。</li>
<li><code>match.params</code> 中包含了 URL 中的动态参数,像这里的 <code>userId</code>。</li>
</ul>
<p>确保在路由配置中使用 <code>UserProfile</code> 组件时,像这样设置路由:</p>
<pre><code class="language-js"><Route path="/users/:userId" element={<UserProfile />} />
</code></pre>
<h4 id="函数组件">函数组件</h4>
<p>直接使用 <code>useParams</code> 来获取 URL 参数:</p>
<pre><code class="language-js">import { useParams } from 'react-router-dom';
function UserProfile() {
const { userId } = useParams();
return <div>User ID: {userId}</div>;
}
</code></pre>
<h3 id="6-获取-修改-查询字符串location">6. 获取 修改 查询字符串(location)</h3>
<p><code>https://example.com/users?userId=123&userName=Alice</code></p>
<h4 id="1-类组件获取查询字符串参数">1. 类组件获取查询字符串参数</h4>
<p>在类组件中,我们通常使用 <code>withRouter</code> 高阶组件来访问路由相关的信息,包括查询字符串。</p>
<p>示例代码</p>
<pre><code class="language-javascript">import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class QueryParamsClassComponent extends Component {
render() {
const { location } = this.props; // 从 props 中获取 location 对象
const searchParams = new URLSearchParams(location.search); // 创建 URLSearchParams 对象
// 获取具体的参数
const userId = searchParams.get('userId'); // 获取 userId 参数
const name = searchParams.get('name'); // 获取 name 参数
// searchParams。set('userId', '456'); // 修改或添加 userId 参数
// searchParams.set('name', 'Alice'); // 修改或添加 name 参数
return (
<div>
<h1>Query Parameters</h1>
<p>User ID: {userId}</p>
<p>Name: {name}</p>
</div>
);
}
}
export default withRouter(QueryParamsClassComponent); // 使用 withRouter 包裹类组件
</code></pre>
<p>代码解析</p>
<ol>
<li><strong>引入 <code>withRouter</code></strong>:首先需要引入 <code>withRouter</code>,它使得组件可以访问路由的 props。</li>
<li><strong>访问 <code>location</code> 对象</strong>:在 <code>render</code> 方法中,从 <code>this.props</code> 中获取 <code>location</code> 对象。</li>
<li><strong>使用 <code>URLSearchParams</code></strong>:
<ul>
<li><code>new URLSearchParams(location.search)</code> 创建一个 <code>URLSearchParams</code> 对象,<code>location.search</code> 包含查询字符串(包括 <code>?</code>)。</li>
<li>通过 <code>get</code> 方法提取具体的参数值,例如 <code>userId</code> 和 <code>name</code>。</li>
</ul>
</li>
<li><strong>渲染参数</strong>:在组件的 JSX 中渲染这些参数。</li>
</ol>
<h4 id="2-函数组件获取查询字符串参数">2. 函数组件获取查询字符串参数</h4>
<p>在函数组件中,我们可以使用 <code>useLocation</code> Hook 来获取路由信息,包括查询字符串。</p>
<p>示例代码</p>
<pre><code class="language-javascript">import React from 'react';
import { useLocation } from 'react-router-dom';
const QueryParamsFunctionComponent = () => {
const location = useLocation(); // 使用 useLocation 获取 location 对象
const searchParams = new URLSearchParams(location.search); // 创建 URLSearchParams 对象
// 获取具体的参数
const userId = searchParams.get('userId'); // 获取 userId 参数
const name = searchParams.get('name'); // 获取 name 参数
//searchParams.get('userId'); // 获取 userId 参数
//searchParams.get('name'); // 获取 name 参数
return (
<div>
<h1>Query Parameters</h1>
<p>User ID: {userId}</p>
<p>Name: {name}</p>
</div>
);
};
export default QueryParamsFunctionComponent; // 直接导出函数组件
</code></pre>
<p>代码解析</p>
<ol>
<li><strong>引入 <code>useLocation</code></strong>:引入 <code>useLocation</code> Hook。</li>
<li><strong>调用 <code>useLocation</code></strong>:在函数组件中调用 <code>useLocation()</code>,它返回当前路由的 <code>location</code> 对象。</li>
<li><strong>使用 <code>URLSearchParams</code></strong>:
<ul>
<li><code>new URLSearchParams(location.search)</code> 创建一个 <code>URLSearchParams</code> 对象,用于解析查询字符串。</li>
<li>使用 <code>get</code> 方法提取需要的参数值。</li>
</ul>
</li>
<li><strong>渲染参数</strong>:在组件的 JSX 中渲染这些参数。</li>
</ol>
<h3 id="7编程导航-history">7、编程导航 history</h3>
<h4 id="1-history-对象的概念">1. <code>history</code> 对象的概念</h4>
<ul>
<li><strong>历史记录</strong>:<code>history</code> 对象是一个 JavaScript 对象,它表示浏览器的会话历史。每当用户访问一个新的 URL 时,浏览器会将该 URL 添加到历史记录中。</li>
<li><strong>导航</strong>:通过 <code>history</code> 对象,你可以编程式地导航到不同的页面,而不是仅仅依赖于用户点击链接。</li>
</ul>
<h4 id="2-history-对象的常用方法">2. <code>history</code> 对象的常用方法</h4>
<p><code>history</code> 对象提供了多种方法来处理导航和历史记录。以下是一些常用的方法:</p>
<p><strong><code>push(path, )</code></strong></p>
<ul>
<li><strong>功能</strong>:在历史记录栈中添加一个新的条目,导航到指定的路径。</li>
<li><strong>参数</strong>:
<ul>
<li><code>path</code>:要导航到的路径。</li>
<li><code>state</code>(可选):与新路径关联的状态对象,这个对象可以在目标页面通过 <code>location.state</code> 访问。</li>
</ul>
</li>
</ul>
<p><strong>示例</strong>:</p>
<pre><code class="language-javascript">this.props.history.push('/home'); // 导航到 /home
this.props.history.push('/profile', { from: 'home' }); // 导航到 /profile,并传递状态
</code></pre>
<p><strong><code>replace(path, )</code></strong></p>
<ul>
<li><strong>功能</strong>:替换当前的历史记录条目,导航到指定的路径,而不是添加一个新的条目。</li>
<li><strong>参数</strong>:同 <code>push</code> 方法。</li>
</ul>
<p><strong>示例</strong>:</p>
<pre><code class="language-javascript">this.props.history.replace('/login'); // 用 /login 替换当前的历史条目
</code></pre>
<p><strong><code>go(n)</code></strong></p>
<ul>
<li><strong>功能</strong>:根据历史记录栈中的位置导航。</li>
<li><strong>参数</strong>:
<ul>
<li><code>n</code>:要导航的相对位置(正数表示向前,负数表示向后)。</li>
</ul>
</li>
</ul>
<p><strong>示例</strong>:</p>
<pre><code class="language-javascript">this.props.history.go(-1); // 返回到上一页
this.props.history.go(2); // 前进两页
</code></pre>
<p><code>goBack()</code> 返回到上一页,等同于 <code>go(-1)</code>。</p>
<p><code>goForward()</code> 前进到下一页,等同于 <code>go(1)</code>。</p>
<h4 id="3-在-react-router-中使用-history">3. 在 React Router 中使用 <code>history</code></h4>
<p>在 React Router 中,<code>history</code> 对象通常是通过 <code>withRouter</code> 高阶组件或在函数组件中通过 <code>useNavigate</code> 和 <code>useLocation</code> Hook 访问的。</p>
<p><strong>类组件使用 <code>withRouter</code></strong></p>
<pre><code class="language-javascript">import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class MyComponent extends Component {
handleNavigation = () => {
this.props.history.push('/home'); // 使用 history 导航
};
render() {
return <button onClick={this.handleNavigation}>Go to Home</button>;
}
}
export default withRouter(MyComponent); // 使用 withRouter 包裹组件
</code></pre>
<p><strong>函数组件使用 <code>useNavigate</code></strong></p>
<p>在 React Router v6 及以上版本中,推荐使用 <code>useNavigate</code> Hook 来获取 <code>navigate</code> 函数。</p>
<pre><code class="language-javascript">import React from 'react';
import { useNavigate } from 'react-router-dom';
const MyFunctionComponent = () => {
const navigate = useNavigate();
const handleNavigation = () => {
navigate('/home'); // 使用 navigate 导航
};
return <button onClick={handleNavigation}>Go to Home</button>;
};
export default MyFunctionComponent;
</code></pre>
<h3 id="8子组件的路由-outlet">8、子组件的路由 Outlet</h3>
<pre><code class="language-js">// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import UserProfile from './UserProfile';
import UserSettings from './UserSettings';
import UserActivity from './UserActivity';
const App = () => {
return (
<Router>
<Routes>
<Route path="/users/*" element={<UserProfile />}>
<Route path="settings" element={<UserSettings />} />
<Route path="activity" element={<UserActivity />} />
</Route>
</Routes>
</Router>
);
};
export default App;
// UserProfile.js
import React from 'react';
import { Link, Outlet } from 'react-router-dom';
const UserProfile = () => {
return (
<div>
<h1>User Profile</h1>
<nav>
<ul>
<li>
<Link to="settings">Settings</Link>
</li>
<li>
<Link to="activity">Activity</Link>
</li>
</ul>
</nav>
<Outlet /> {/* 渲染匹配的子路由 */} // 路由
</div>
);
};
export default UserProfile;
// UserSettings.js
import React from 'react';
const UserSettings = () => {
return <h2>User Settings</h2>;
};
export default UserSettings;
// UserActivity.js
import React from 'react';
const UserActivity = () => {
return <h2>User Activity</h2>;
};
export default UserActivity;
</code></pre>
<h2 id="7redux-集中状态管理">7、redux 集中状态管理</h2>
<p><code>Redux.createStore</code> 是 Redux 的传统方式,用于创建 Redux store。</p>
<h3 id="reduxcreatestore"><code>Redux.createStore</code></h3>
<ol>
<li><strong>导入 Redux</strong>:</li>
</ol>
<pre><code class="language-javascript">import { createStore } from 'redux';
</code></pre>
<ol start="2">
<li><strong>定义初始状态</strong>:</li>
</ol>
<pre><code class="language-javascript">const initialState = {
todos: [],
};
</code></pre>
<ol start="3">
<li><strong>创建 Reducer</strong>:</li>
</ol>
<p>Reducer 是一个纯函数,接受当前状态和 action,并返回新的状态。</p>
<pre><code class="language-javascript">const todoReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_TODO':
return { ...state, todos: [...state.todos, action.payload] };
default:
return state;
}
};
</code></pre>
<ol start="4">
<li><strong>创建 Store</strong>:</li>
</ol>
<p>使用 <code>createStore</code> 创建 store,并传入 reducer。</p>
<pre><code class="language-javascript">const store = createStore(todoReducer);
</code></pre>
<ol start="5">
<li><strong>使用 Store</strong>:</li>
</ol>
<p>可以使用 <code>store.getState()</code> 获取当前状态,使用 <code>store.dispatch(action)</code> 发送 action。</p>
<pre><code class="language-javascript">store.dispatch({ type: 'ADD_TODO', payload: { text: 'Learn Redux' } });
console.log(store.getState());
</code></pre>
<h3 id="redux-toolkit"><code>Redux Toolkit</code></h3>
<p>Redux Toolkit 是官方推荐的 Redux 工具集,它简化了 Redux 的使用,包含了一些开箱即用的工具和最佳实践。使用 Redux Toolkit 可以更容易地管理状态,减少模板代码。</p>
<h4 id="1-安装">1. 安装</h4>
<p>首先,安装 Redux Toolkit 和 React-Redux:</p>
<pre><code class="language-bash">npm install @reduxjs/toolkit react-redux
</code></pre>
<h4 id="2-创建-slice">2. 创建 Slice</h4>
<p>使用 <code>createSlice</code> 来定义 state、reducers 和 actions。这样可以简化代码结构。</p>
<pre><code class="language-javascript">import { createSlice } from '@reduxjs/toolkit';
const todosSlice = createSlice({
name: 'todos',
initialState: [], // 要存的state
// 使用 createSlice 创建 slice 时,定义的 reducer 函数会自动生成对应的 action creators。
reducers: {
addTodo: (state, action) => { // state中包含所有 initialState 中的数据,
state.push(action.payload); // 使用 Immer 库来处理不可变状态
},
removeTodo: (state, action) => {
return state.filter(todo => todo.id !== action.payload); // payload 包含了调用时传递的参数, 可以是对象
},
},
});
// 导出 action
export const { addTodo, removeTodo } = todosSlice.actions;
// 导出 reducer
export default todosSlice.reducer;
</code></pre>
<h4 id="3-配置-store">3. 配置 Store</h4>
<p>使用 <code>configureStore</code> 来创建 store,它会自动添加 Redux DevTools 支持和中间件。</p>
<pre><code class="language-javascript">import { configureStore } from '@reduxjs/toolkit';
import todosReducer from './todosSlice';
const store = configureStore({
reducer: {
todos: todosReducer,
},
});
export default store;
</code></pre>
<h4 id="4-连接-react-和-redux">4. 连接 React 和 Redux</h4>
<p>在应用中使用 <code>Provider</code> 将 store 传递给组件树。</p>
<pre><code class="language-javascript">import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
</code></pre>
<h4 id="5-使用-redux-state">5. 使用 Redux State</h4>
<p>在组件中使用 <code>useSelector</code> 和 <code>useDispatch</code> 来访问状态和发起 action。</p>
<pre><code class="language-javascript">import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { addTodo, removeTodo } from './todosSlice';
const TodoList = () => {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();
const handleAddTodo = () => {
const text = prompt('Enter todo:');
const id = Date.now(); // 简单生成 ID
dispatch(addTodo({ id, text }));
};
const handleRemoveTodo = (id) => {
dispatch(removeTodo(id));
};
return (
<div>
<h1>Todo List</h1>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => handleRemoveTodo(todo.id)}>Remove</button>
</li>
))}
</ul>
<button onClick={handleAddTodo}>Add Todo</button>
</div>
);
};
export default TodoList;
</code></pre>
<h4 id="6-处理异步操作">6. 处理异步操作</h4>
<p>使用 <code>createAsyncThunk</code> 处理异步请求。</p>
<pre><code class="language-javascript">import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 异步操作示例
export const fetchTodos = createAsyncThunk('todos/fetchTodos', async () => {
const response = await fetch('/api/todos');
return response.json();
});
const todosSlice = createSlice({
name: 'todos',
initialState: { items: [], status: 'idle' },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchTodos.fulfilled, (state, action) => {
state.items = action.payload;
});
},
});
// 导出 reducer
export default todosSlice.reducer;
</code></pre>
<h2 id="8hook">8、hook</h2>
<p>好的,我们来详细讲解一下 React Hooks,包括基本用法、常见的 Hooks 和具体的应用场景。</p>
<h3 id="1基本用法">1、基本用法</h3>
<p>React Hooks 是 React 16.8 引入的一种新特性,旨在让函数组件具备类组件的功能,尤其是状态管理和副作用处理。Hooks 的引入使得函数组件更加强大和灵活。</p>
<h4 id="1-使用-hooks-的规则">1. 使用 Hooks 的规则</h4>
<ul>
<li><strong>只能在函数组件或自定义 Hooks 中调用。</strong> 不可以在 <code>普通 JavaScript 函数</code>、<code>类组件</code> 或者 <code>条件语句</code> 中调用。</li>
<li><strong>调用顺序必须一致。</strong> React 会根据调用的顺序来追踪每个 Hook 的状态。</li>
</ul>
<h3 id="2常见的-hooks">2、常见的 Hooks</h3>
<h4 id="1-usestate">1. <code>useState</code></h4>
<p>用于在函数组件中添加状态。</p>
<pre><code class="language-javascript">import React, { useState } from 'react';
function Counter() {
const = useState(0); // count 是状态,setCount 是更新状态的函数
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
</code></pre>
<h4 id="2-useeffect">2. <code>useEffect</code></h4>
<p><code>useEffect(()=> {}, 依赖项)</code><br>
<img src="https://i-blog.csdnimg.cn/direct/aba9e3fac1f4437c99ef085a865bdc59.png" alt="在这里插入图片描述" loading="lazy"></p>
<p>用于处理副作用,例如数据获取、订阅等。</p>
<pre><code class="language-javascript">import React, { useState, useEffect } from 'react';
function DataFetcher() {
const = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
// 可选的清理函数
return () => {
// 例如取消订阅
};
}, []); // 依赖数组,空数组意味着仅在组件挂载时执行一次
return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}
</code></pre>
<h4 id="3-usecontext">3. <code>useContext</code></h4>
<p>用于在组件之间共享状态,避免逐层传递 props。</p>
<pre><code class="language-javascript">import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function ThemedComponent() {
const theme = useContext(ThemeContext);
return <div className={theme}>Current theme: {theme}</div>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedComponent />
</ThemeContext.Provider>
);
}
</code></pre>
<h4 id="4-usereducer">4. <code>useReducer</code></h4>
<p>用于在复杂状态逻辑中管理状态,相比 <code>useState</code> 更加灵活。</p>
<pre><code class="language-javascript">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 = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
</code></pre>
<h4 id="5-自定义-hooks">5. 自定义 Hooks</h4>
<p>你可以创建自己的 Hooks,复用逻辑。</p>
<pre><code class="language-javascript">import { useState, useEffect } from 'react';
function useFetch(url) {
const = useState(null);
const = useState(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(setData)
.catch(setError);
}, );
return { data, error };
}
// 使用自定义 Hook
function DataFetcher({ url }) {
const { data, error } = useFetch(url);
if (error) return <div>Error: {error.message}</div>;
return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}
</code></pre>
<h3 id="3具体的应用场景">3、具体的应用场景</h3>
<ol>
<li><strong>数据获取</strong>: 使用 <code>useEffect</code> 和 <code>useState</code> 来从 API 获取数据。</li>
<li><strong>表单管理</strong>: 使用 <code>useState</code> 来管理输入框的状态,并处理提交。</li>
<li><strong>动画</strong>: 使用 <code>useEffect</code> 来设置动画的入场和离场。</li>
<li><strong>订阅</strong>: 在 <code>useEffect</code> 中添加订阅,返回一个清理函数以取消订阅。</li>
<li><strong>组合逻辑</strong>: 使用自定义 Hooks 来提取组件之间共享的逻辑。</li>
</ol><br><br>
来源:https://www.cnblogs.com/xxctx/p/18449900
頁:
[1]