使用React + TypeScript: 学习React官方文档中的基础解释”Learn React”

React公式文档网站react.dev已于2023年3月16日进行了更新(请参考博客“介绍react.dev”)。在基础解释的“学习React”部分,内容包含了适用于初学者的详细说明以及对中级开发者有帮助的深入信息。

我在一个包含TypeScript的环境中重新解释这些文章,并在Qiita上发布了它们。由于数目有些增加,我将我的Qiita文章和官方网站的对应链接整理在一起,并在此文中附上了简单介绍。每篇解释基本都包含了官方文章的信息,但并非翻译成日文。我补充了不足之处,改变了说明方式,并删除了不必要的描述。此外,我添加了对TypeScript的前提条件,因此省略了JavaScript的基础说明。

此外,一些代码示例已在CodeSandbox上发布,如果你有兴趣,可以实际尝试一下。

[2023/08/16] 添加了「利用自定义钩子重用逻辑」。

描述用户界面

构建用户界面

    Describing the UI

这个主题是关于React组件以及JSX返回值的写法。在React应用中,我们通过组合组件并使用JSX来渲染页面。

增加互动性

处理发生的事件

    Responding to Events

以下是需要解释的项目。

    • イベントハンドラをどう定め方るか。

 

    • イベント処理のロジックを親コンポーネントから子にどのように渡すか。

 

    イベントの制御の仕方。

React的事件处理程序可以作为JSX的属性添加,并提供处理程序(回调)函数。它是响应鼠标点击、指针交叉、表单输入聚焦等交互操作而调用的函数。

保持组件的状态

    State: A Component’s Memory

根据组件交互的不同,可能需要更改屏幕内容。举个例子,就像这样的情况。

    • フォームに入力したときテキストフィールドの更新。

 

    • カルーセルで[つぎへ]のボタンをクリックしたときの画像の切り替え。

 

    商品の[購入]ボタンクリックによるショッピングカートへの追加。

在React中,组件必须记住这些变更的当前值。React中,为每个组件存储值的机制称为状态(state)。

渲染和提交

    Render and Commit

在React将组件渲染到屏幕之前,组件必须进行渲染。假设组件就像一位餐厅的厨师,那么React就扮演着基于订单为客人送菜的服务员的角色。

    1. 启动渲染器:将客人的订单送到厨房。

 

    1. 渲染组件:在厨房里完成烹饪工作。

 

    提交到DOM:将菜品送到客人的餐桌。

作为快照的状态

    State as a Snapshot

状态变量可能看起来像是可以读写值的标准JavaScript变量。但是,状态的行为更接近于“快照”(作者注:记录当前信息的记录)。状态的设置并不是对已经确定的值进行更改,而是触发重新渲染。

将连续的状态变更加入队列进行处理。

    Queueing a Series of State Updates

当设置状态变量时,渲染将被排入队列。然而,在下一个渲染被加入队列之前,可能会希望对变量值进行多个操作。为了做到这一点,了解React如何对状态更新进行批处理将会很有帮助。

更新已保存的对象状态。

    Updating Objects in State

在React中,可以保存的状态是包括对象在内的所有JavaScript值。然而,不应直接修改状态中的对象。当想要更新时,首先创建一个新的对象(或者原始对象的副本)并进行编辑。然后,使用该对象来设置状态。

更新保存在状态中的数组。

    Updating Arrays in State

在JavaScript中,数组是可变的。但是,在React中将其置于状态中时,请将其视为不可变的。数组也是对象。因此,在更新放入状态的数组时,首先需要创建一个新的数组(或原始数组的副本)。然后,进行编辑并将其设置为状态。

管理国家

将输入与状态产生反应

    Reacting to Input with State

React使用的UI操作方法是声明性的。它不直接操作每个UI部分。它描述了组件可以采取的不同状态,并根据用户输入进行切换。这与设计师考虑UI有些相似。

选择状态结构

    Choosing the State Structure

状態を適切に構造化するかどうかは、コンポーネントの変更やデバッグのしやすさ、または逆にバグに悩むこととの違いに直結します。以下に、状態を構造化する際に考慮すべき要素を紹介します。

在组件之间共享状态

    Sharing State Between Components

如果我们希望两个组件的状态始终一起变化,可以将状态移到最近的共同父组件中,而不是在每个组件中都维护一个状态。然后,我们可以通过属性将值从父组件传递给子组件。这被称为状态提升(Lift-Up),在React代码中经常使用。

狀態保存與重置

    Preserving and Resetting State

每个组件具有不同的状态。React根据状态所属的组件以及其在UI树中的位置来了解状态。在重新渲染之间,我们可以控制何时保留状态以及何时重置状态。

将状态逻辑切分到还原器中。

    Extracting State Logic into a Reducer

当一个组件具有多个跨越许多事件处理程序的不同状态更新时,变得难以处理。在这种情况下,可以将所有状态更新逻辑从组件中剥离出来,并整合到一个函数中。这就是所谓的Reducer(纯函数)。

在上下文中将数据传递到深层次

    Passing Data Deeply with Context

一般情况下,父组件通过属性将信息传递给子组件。然而,在以下情况下使用属性会变得冗长且不方便。

    • 間に多くのコンポーネントを経て渡すことになってしまう(いわゆる「バケツリレー」)。

 

    アプリケーション内の多くのコンポーネントが同じ情報を必要としている。

如果使用上下文,父组件的信息可以在树的任何子组件中被引用,无论树的深度如何,也不需要通过属性来传递。

通过使用适当的减压工具和环境来提高扩展性

    Scaling Up with Reducer and Context

通过整合组件状态更新逻辑,Reducer(减法器)可以使得复杂屏幕状态的管理更加便捷。此外,通过使用上下文(Context),您可以将信息传递给更深层次的其他组件。将这两者结合起来,将能够更好地管理复杂屏幕的状态。

逃生通道

在ref中引用值

    Referencing Values with Refs

当使用ref时,可以将某些信息“存储”到组件中,同时不会产生基于该信息的新渲染。

通过ref来操作DOM

    Manipulating the DOM with Refs

React自动更新和呈现DOM输出的过程是自动的。因此,组件不必经常操作DOM。但是,在某些情况下,可能需要引用DOM并让React进行操作。例如,以下情况。

    • ノードにフォーカスしたい。

 

    • ノードをスクロールさせたい。

 

    ノードのサイズや位置を調べたい。

然而,React并没有这样的内置机制,因此我们需要使用ref来引用DOM节点。

使用React和TypeScript:使用效果进行同步

    Synchronizing with Effects

有些组件需要与外部系统进行同步。例如,以下情况:

    • React以外のコンポーネントを状態にもとづいて制御したいとき。

 

    • サーバーとの接続を確立したいとき。

 

    分析用のログをコンポーネントが画面に表示されたら送りたいとき。

在渲染之后,效果会执行该代码。这样,React 组件与系统外部的组件可以进行同步。

如果不需要使用效果(useEffect)的情况下

    You Might Not Need an Effect

效果是从React的机制中的非常口。您可以使用React与外部系统“对接”并同步组件。例如,与React无关的小部件,网络,或者浏览器DOM等。如果不涉及外部系统,则不需要效果。当您想要更新属性或状态发生更改时,才需要使用效果来更新组件的状态。通过排除不必要的效果,代码会更易于理解,执行速度更快,错误更少发生。

React的副作用(useEffect)生命周期

    Lifecycle of Reactive Effects

特效和组件有不同的生命周期。

    • コンポーネント

マウント
更新
アンマウント

エフェクト

同期の開始
同期の停止

如果特定效果所依赖的属性或状态随时间而变化,那么其生命周期可能会重复出现。借助React提供的lint规则,可以检查效果是否正确地依赖了特定内容。这样,效果就能与最新的属性和状态保持同步。

将活动和效果的逻辑分开。

    Separating Events from Effects

事件处理程序只在执行预先定义的交互时再次运行。与此相反,如果读取的属性或状态变量的值与上次渲染时不同,则会重新同步,这就是效果。在某些情况下,可能希望将两种动作组合在一起。这就是在特定值时重新执行效果,而对其他值不做响应的情况。让我们来解释一下这种处理的思想。

除去依赖于效果的部分。

    Removing Effect Dependencies

当编写效果时,linter将检查代码中是否包含了响应式值(如属性和状态)。这些值必须都被添加到效果所读取的依赖数组中。这样一来,效果就能与组件的最新属性和状态保持同步。如果包含了不必要的依赖值,效果可能会被多次执行或引发无限循环。本文将解释如何找到和消除效果中不必要的依赖值。

当编写效果时,lint会检查代码中是否包含了(诸如属性或状态等的)反应性值。这些值必须都添加到效果读取的依赖数组中。这样,效果就能保持与组件的最新属性和状态同步。如果包含了不必要的依赖值,效果可能会被多次执行或导致无限循环。本文将解释如何找到和移除效果中的不必要的依赖值。

通过自定义钩子来重用逻辑

    Reusing Logic with Custom Hooks

React中提供了各种内置的钩子,例如useState、useContext、useEffect等等。但是,有时候我们可能需要更特定目的的钩子。以下是一些示例用途。

    • データの取得。

 

    • ユーザがオンラインかどうかの監視。

 

    チャットルームへの接続。

也许在React的内置钩子中找不到这个功能,但是根据应用需求,可以自己制作钩子。

广告
将在 10 秒后关闭
bannerAds