高级React组件

本章将重点介绍高级 React 组件的实现。我们将了解什么是高阶组件以及如何实现它们。此外,我们还将深入探讨 React 中更高级的主题,并用它实现复杂的交互功能。

引用 DOM 元素

有时候我们需要在 ReactDOM 节点进行交互。 ref 属性可以让我们访问元素中的一个节点,通常,访问 DOM 节点是 React 中的一个反模式,因为我们应该遵循它的声明式编程和单向数据流。当我们引入第一搜索组件时,就已经了解刀这些问题,但是在某些情况下,我们仍然要访问 DOM 节点。官方文档提到了三种情况

使用 DOM API(focus事件,媒体播放等)

调用命令式 DOM 节点动画

与需要 DOM 节点的第三方库集成

让我们通过 Search 组件这个例子看一下。当应用程序第一次渲染时,input 字段应该被聚焦。这是需要访问 DOM API 的一种用例。本章将展示渲染时聚焦 input 字段是如何工作的,但由于这个功能对于应用程序并不是很有用,所以我们将在本章之后省略这些更改。尽管如此,你仍然可以为自己的应用程序保留它。

通常,无状态组件ES6 类组件中都可以使用 ref 属性。在聚焦 input 字段的用例中,我们就需要一个生命周期方法。这就是为什么接下来会先在 ES6 类组件中展示如何使用 ref 属性。

第一步是将无状态组件重构为 ES6 类组件。

class Search extends Component {
render() {
const {
value,
onChange,
onSubmit,
children
} = this.props; return (
<form onSubmit={onSubmit}>
<input
type="text"
value={value}
onChange={onChange}
/>
<button type="submit">
{children}
</button>
</form>
);
}
}

ES6 类组件的this对象可以帮助我们通过 ref 属性引用 DOM 节点。

class Search extends Component {
render() {
const {
value,
onChange,
onSubmit,
children
} = this.props; return (
<form onSubmit={onSubmit}>
<input
type="text"
value={value}
onChange={onChange}
ref={(node) => { this.input = node; }}
/>
<button type="submit">
{children}
</button>
</form>
);
}
}

现在,你可以通过使用 this 对象、适当的生命周期方法和 DOM API 在组件挂载的时候来聚焦 input 字段

lass Search extends Component {
componentDidMount() {
if(this.input) {
this.input.focus();
}
} render() {
const {
value,
onChange,
onSubmit,
children
} = this.props; return (
<form onSubmit={onSubmit}>
<input
type="text"
value={value}
onChange={onChange}
ref={(node) => { this.input = node; }}
/>
<button type="submit">
{children}
</button>
</form>
);
}
}

当应用程序渲染时,input 字段应该被聚焦。这就是ref属性的基本用法。

但是我们怎样在没有this对象的无状态组件中访问ref属性呢?接下来我们在无状态组件中演示。

const Search = ({
value,
onChange,
onSubmit,
children
}) => {
let input;
return (
<form onSubmit={onSubmit}>
<input
type="text"
value={value}
onChange={onChange}
ref={(node) => input = node}
/>
<button type="submit">
{children}
</button>
</form>
);
}

加载

现在让我们回到应用程序。当向 Hacker News API 发起搜索请求时,我们想要显示一个加载指示符。

请求是异步的,此时应该向用户展示某些事情即将发生的某种反馈。让我们在 src/App.js 中定义一个可重用的 Loading 组件。

const Loading = () =>

<div>Loading ...</div>

现在你将需要一个属性来存储加载状态。根据加载状态可以决定稍后是否显示所加载的组件。

src/App.js

class App extends Component {
constructor(props) {
super(props); this.state = {
results: null,
searchKey: '',
searchTerm: DEFAULT_QUERY,
error: null,
isLoading: false,
}; ...
} ... }

isLoading 的初始值是 false。在 App 组件挂载完成之前,无需加载任何东西。

当发起请求时,将加载状态 (isLoading) 设置为 true。最终,请求会成功,那时可以将加载状态 (isLoading) 设置为 false。

src/App.js

class App extends Component {

...

setSearchTopStories(result) {
... this.setState({
results: {
...results,
[searchKey]: { hits: updatedHits, page }
},
isLoading: false
});
} fetchSearchTopStories(searchTerm, page = 0) {
this.setState({ isLoading: true }); fetch(`${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${searchTerm}&${PARAM_PAGE}\
${page}&${PARAM_HPP}${DEFAULT_HPP}`)
.then(response => response.json())
.then(result => this.setSearchTopStories(result))
.catch(e => this.setState({ error: e }));
} ... }

最后一步,我们将在应用程序中使用 Loading 组件。基于加载状态 (isLoading) 的条件来决定渲染 Loading 组件或 Button 组件。后者为一个用于获取更多数据的按钮。

src/App.js

class App extends Component {

    ...

    render() {
const {
searchTerm,
results,
searchKey,
error,
isLoading
} = this.state; ... return (
<div className="page">
...
<div className="interactions">
{ isLoading
? <Loading />
: <Button
onClick={() => this.fetchSearchTopStories(searchKey, page + 1)}>
More
</Button>
}
</div>
</div>
);
}
}

由于我们在componentDidMount()中发起请求,Loading 组件会在应用程序启动的时候显示。此时,因为列表是空的,所以不显示 Table 组件。当响应数据从 Hacker News API 返回时,返回的数据会通过 Table 组件显示出来,加载状态 (isLoading) 设置为 false,然后 Loading 组件消失。同时,出现了可以获取更多的数据的“More”按钮。一旦点击按钮,获取更多的数据,该按钮将消失,加载组件会重新出现。

高阶组件

高阶组件(HOC)是 React 中的一个高级概念。HOC 与高阶函数是等价的。它接受任何输入 - 多数时候是一个组件,也可以是可选参数 - 并返回一个组件作为输出。返回的组件是输入组件的增强版本,并且可以在JSX中使用。

HOC可用于不同的情况,比如:准备属性,管理状态或更改组件的表示形式。其中一种情况是将 HOC 用于帮助实现条件渲染。想象一下现在有一个 List 组件,由于列表可以为空或无,那么它可以渲染一个列表或者什么也不渲染。当没有列表的时候,HOC 可以屏蔽掉这个不显示任何内容的列表。另一方面,这个简单的 List 组件不再需要关心列表存不存在,它只关心渲染列表。

高级排序

我们已经实现了客户端和服务器端搜索交互。因为我们已经拥了 Table 组件,所以增强 Table 组件的交互性是有意义的。那接下来,我们为 Table 组件加入根据列标题进行排序的功能如何?

你自己写一个排序函数,但是一般这种情况,我个人更喜欢使用第三方工具库。lodash就是这些工具库之一,当然你也可以选择适用于你的任何第三方库。让我们安装 lodash 并使用。

参考链接:https://leanpub.com/the-road-to-learn-react-chinese

The Road to learn React书籍学习笔记(第四章)的更多相关文章

  1. The Road to learn React书籍学习笔记(第三章)

    The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...

  2. The Road to learn React书籍学习笔记(第二章)

    The Road to learn React书籍学习笔记(第二章) 组件的内部状态 组件的内部状态也称为局部状态,允许保存.修改和删除在组件内部的属性,使用ES6类组件可以在构造函数中初始化组件的状 ...

  3. The Road to learn React书籍学习笔记(第一章)

    react灵活的生态圈 Small Application Boilerplate: create-react-app Utility: JavaScript ES6 and beyond Styli ...

  4. [Python学习笔记][第四章Python字符串]

    2016/1/28学习内容 第四章 Python字符串与正则表达式之字符串 编码规则 UTF-8 以1个字节表示英语字符(兼容ASCII),以3个字节表示中文及其他语言,UTF-8对全世界所有国家需要 ...

  5. 《metasploit渗透测试魔鬼训练营》学习笔记第四章—web应用渗透

    继续来学习metasploit...记好笔记是很重要的,下面开始正文: 二.WEB应用渗透技术     1.WEB应用渗透基础知识        先介绍WEB应用攻击的主要类型(大致介绍,具体请自行查 ...

  6. [core java学习笔记][第四章对象与类]

    4.3 用户自定义类 4.3.1 类数组的声明 需要两次new Employee[]=staff=new Employedd[3]; staff[0]=new Employedd(参数列表); sta ...

  7. Java 学习笔记 ------第四章 认识对象

    本章学习目标: 区分基本类型与类类型 了解对象与参考的关系 从打包器认识对象 以对象观点看待数组 认识字符串的特性 一."=" 和 "==" 当=用于基本类型时 ...

  8. c语言学习笔记第四章——字符串和格式化输入、输出

    B站有视频演示 本章学习printf函数的输入输出,字符串的定义与实用. 字符串 字符串(character string)是一个或多个字符的序列,如下所示: "Zing went the ...

  9. 《Python基础教程(第二版)》学习笔记 -> 第四章 字典

    字典是Python中唯一内建的映射类型. 字典中的值并没有特殊的顺序,但是都存储在一个特定的键(Key)里.键可以是数字.字符串甚至是元组. 字典的使用 某些情况下,字典比列表更加适用: 表征游戏棋盘 ...

随机推荐

  1. ORACLE_PROCEDURE_DROPTABLE

    WEBSITE:https://stackoverflow.com/questions/14564641/drop-a-table-in-a-procedure Qusetion:Hou to use ...

  2. python编写脚本,删除固定用户下的所有表

    脚本如下: [oracle@ycr python]$ more t_del.py #/usr/bin/python#coding:utf8 import sysimport cx_Oracle i=0 ...

  3. Android(java)学习笔记51:ScrollView用法

    1. 理论部分 (1)ScrollView和HorizontalScrollView是为控件或者布局添加滚动条 (2)上述两个控件只能有一个孩子,但是它并不是传统意义上的容器 (3)上述两个控件可以互 ...

  4. SSD 从形式到实质之改变

    SSD 从形式到实质之改变  作者:廖恒          SSD的物理尺寸之混战正在进行其中. 数据中心的硬件架构师由于要规划下一代server的机械设计.还要制定JBOD的设计规范,想必面临不少困 ...

  5. HDU 3336 KMP

    题意:求每一个前缀,跟前缀相同的每个子串. 此题:网上很多都是假程序,不过也AC了,的确我测试几个案例之后的的确确是存在这个问题. 分析:每一个前缀,可以考虑KMP,f失配指针,如何求得它出现了多少次 ...

  6. winform 实现彩票功能

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/MrTraum/article/details/32702319 watermark/2/text/a ...

  7. activeMQ消息队列的使用

    ActiveMQ解决问题:  1.解决服务之间的耦合 2.增加系统并发处理量. 它使用的是标准生产者和消费者模型.有两种数据结构:Queue/Topic 1.Queue队列,生产者生产一个消息,只能由 ...

  8. 【洛谷P1288】取数游戏II

    取数游戏II 题目链接 显然,由于一定有一个0,我们可以求出从初始点到0的链的长度 若有一条链长为奇数,则先手可以每次取完一条边上所有的数, 后手只能取另一条边的数,先手必胜: 反之若没有奇数链,后手 ...

  9. 【洛谷P2607】[ZJOI2008]骑士

    骑士 题目链接 这道题一看,似乎和舞会是一样的,然而它并没有保证是一棵树 但是,对于每个连通块,必有相同的点数和边数,这样的图一定是一棵树上加一条边 这条边一定回使图中形成一个环,这种图貌似叫“基环树 ...

  10. google为什么将爬虫从python移植到C++

    这是好几年前Quora上的一个问题,有点过时,但看了之后感觉不错,就总结了一下 原文链接:http://www.quora.com/Why-did-Google-move-from-Python-to ...