Из этого туториала вы узнаете, как использовать Axios для извлечения данных, а затем, как манипулировать ими и, в конечном итоге, отображать их на своей странице с функцией фильтрации. Вы узнаете, как пользоваться картой, фильтровать и включать методы по пути. Кроме того, вы будете создавать компонент высшего порядка (HOC) для обработки состояния загрузки выбранных данных из конечной точки API.
Давайте начнем с чистого приложения React. Я предполагаю, что вы используете create-react-app
, и имена файлов будут в соответствии с его выводами.
Нам нужно только установить модуль Axios для этого урока.
Перейдите в каталог вашего проекта через окно терминала и введите npm install axios -save
, чтобы установить Axios для вашего проекта локально.
Извлечение данных
Мы будем использовать API генератора случайных пользователей для получения информации о случайных пользователях для использования в нашем приложении.
Давайте добавим модуль App.js
в наше приложение, импортировав его в наш файл App.js
1
|
import axios from ‘axios’
|
API генератора случайных пользователей предлагает множество вариантов для создания различных типов данных. Вы можете проверить документацию для получения дополнительной информации, но для этого урока мы будем просты.
Мы хотим получить десять разных пользователей, и нам нужны только имя, фамилия и уникальный идентификатор, который требуется для React при создании списков элементов. Также, чтобы сделать вызов немного более конкретным, давайте включим в качестве примера опцию национальности.
Ниже приведен API, к которому мы будем обращаться.
Обратите внимание, что я не использовал опцию id
предоставленную в API, из-за того, что иногда для некоторых пользователей она возвращает null
. Итак, просто чтобы убедиться, что для каждого пользователя будет уникальное значение, я включил registered
опцию в API.
https://randomuser.me/api/?results=10&inc=name,registered&nat=fr
Вы можете скопировать и вставить его в свой браузер, и вы увидите возвращенные данные в формате JSON.
Теперь, следующая вещь, это сделать вызов API через Axios.
Прежде всего, давайте создадим состояние, чтобы мы могли хранить извлеченные данные.
Внутри нашего компонента App
добавьте конструктор класса, а затем создайте состояние.
1
2
3
4
5
6
7
|
constructor(props){
super(props)
this.state = {
users: [],
store: []
}
}
|
Здесь вы видите users
и состояние store
. Один будет использоваться для целей фильтрации и не будет редактироваться, а другой будет содержать результаты фильтрации, которые будут показаны в DOM.
Теперь давайте создадим хук жизненного цикла componentDidMount()
.
Внутри этого хука жизненного цикла мы будем извлекать данные, а затем, используя метод map
, создадим новые промежуточные данные, которые мы будем использовать внутри метода setState
.
Если вы проверите результат вызова API в своем браузере, вы увидите, что в объекте имени есть первая и последняя пары ключ-значение, но нет пары ключ-значение для полного имени. Таким образом, мы будем объединять первое и последнее, чтобы создать полное имя внутри нового объекта JavaScript. Обратите внимание, что JSON и JavaScript Object — разные вещи, хотя в основном они работают одинаково.
Давайте двигаться шаг за шагом.
Добавьте следующий код в компонент App
.
1
2
3
4
|
componentDidMount(){
axios.get(‘https://randomuser.me/api/?results=10&inc=name,registered&nat=fr’)
.then(json => console.log(json))
}
|
Когда вы проверите консоль, вы увидите вывод объекта. Если вы откроете этот объект, внутри него появится другой объект с именем data
, а внутри data — массив с именем results
.
Давайте далее изменим console.log(json)
.
1
2
3
4
|
componentDidMount(){
axios.get(‘https://randomuser.me/api/?results=10&inc=name,registered&nat=fr’)
.then(json => console.log(json.data.results[0].name.first))
}
|
Здесь мы достигли имени первого значения в массиве результатов.
Теперь давайте воспользуемся встроенным в JavaScript методом map
чтобы выполнить итерацию каждого элемента в массиве и создать новый массив объектов JavaScript с новой структурой.
1
2
3
4
5
6
7
8
9
|
componentDidMount(){
axios.get(‘https://randomuser.me/api/?results=10&inc=name,registered&nat=fr’)
.then(json => json.data.results.map(result => (
{
name: `${result.name.first} ${result.name.last}`,
id: result.registered
})))
.then(newData => console.log(newData))
}
|
Здесь мы вызвали метод map
для json.data.results
, который является массивом, а затем сослались на каждый элемент массива как на result
(обратите внимание на разницу в единственном / множественном числе). Затем, используя пару ключ-значение каждого объекта в массиве, мы создали еще один объект с парами ключ-значение name и id .
В конце мы использовали другой метод then
, чтобы иметь возможность ссылаться на наши новые данные. Мы назвали его как newData
, а затем просто вошли в консоль, чтобы увидеть, все ли прошло как запланировано.
Вы должны увидеть новый массив с объектами, имеющими пары name и id .
Хранение данных
Вместо записи результата на консоль, мы должны сохранить его. Для этого мы будем использовать setState
.
01
02
03
04
05
06
07
08
09
10
|
componentDidMount(){
axios.get(‘https://randomuser.me/api/?results=10&inc=name,registered&nat=fr’)
.then(json => json.data.results.map(result => (
{
name: `${result.name.first} ${result.name.last}`,
id: result.registered
})))
.then(newData => this.setState({users: newData, store: newData}))
.catch(error => alert(error))
}
|
Здесь мы изначально устанавливаем users
и store
данные с нашим новым массивом newData
.
Нам нужны две переменные из-за того, что нам нужно хранить исходные данные и никогда не потерять их. Используя информацию в состоянии store
, мы можем отфильтровать данные, а затем заполнить состояние users
и показать их на странице. Это будет понятнее, когда мы реализуем функцию фильтрации.
И последнее, но не менее важное: мы добавили функцию catch
чтобы фактически перехватывать любые возможные ошибки во время выборки и отображать ошибку в виде предупреждающего сообщения.
Функциональность фильтрации
Идея фильтрации довольно проста. У нас есть состояние store
, и оно всегда сохраняет исходные данные без изменений. Затем, используя функцию filter
для этого состояния, мы только получаем соответствующие элементы и затем назначаем их состоянию users
.
1
|
this.state.store.filter(item => item.name.toLowerCase().includes(e.target.value.toLowerCase()))
|
Метод filter
требует функции в качестве аргумента, функцию, которая должна быть запущена для каждого элемента в массиве. Здесь мы называем каждый элемент в массиве как item
. Затем мы берем ключ имени каждого item
и преобразуем его в нижний регистр, чтобы сделать нашу функцию фильтрации нечувствительной к регистру.
После того, как у нас есть ключ name
для item
, мы проверяем, включает ли он в себя строку поиска, которую мы ввели. includes
— это еще один встроенный метод JavaScript. Мы передаем строку поиска, введенную в поле ввода, в качестве аргумента для includes
, и она возвращает, если эта строка включена в переменную, для которой она была вызвана. Опять же, мы конвертируем входную строку в нижний регистр, чтобы не имело значения, вводите ли вы строчные или прописные буквы.
В конце метод filter возвращает соответствующие элементы. Поэтому мы просто берем эти элементы и сохраняем их в состоянии users
через setState
.
Ниже вы можете найти окончательную версию функции, которую мы создали.
1
2
3
|
filterNames(e){
this.setState({users: this.state.store.filter(item => item.name.toLowerCase().includes(e.target.value.toLowerCase()))})
}
|
Создание компонентов
Хотя для этого небольшого примера мы могли бы поместить все внутри компонента App
, давайте воспользуемся преимуществами React и создадим несколько небольших функциональных компонентов / компонентов без состояния.
Давайте добавим следующую структуру в метод render
компонента App
.
01
02
03
04
05
06
07
08
09
10
|
render() {
const {users} = this.state
return (
<div className=»Card»>
<div className=»header»>NAME LIST</div>
<SearchBar searchFunc={(e) => this.filterNames(e)}/>
<List usernames={users}/>
</div>
);
}
|
В настоящее время мы сосредоточимся только на функциональности. Позже я предоставлю созданный мной файл CSS.
Обратите внимание, что у нас есть реквизиты searchFunc
для компонента SearchBar
и реквизиты usernames
для компонента List
.
Обратите внимание, что мы используем состояние users
вместо состояния store
для отображения данных, потому что это состояние users
содержащее отфильтрованные результаты.
Компонент SearchBar
Этот компонент довольно прост. Он принимает функцию filterNames
в качестве реквизита и вызывает эту функцию при изменении поля ввода.
01
02
03
04
05
06
07
08
09
10
11
|
import React from ‘react’
const SearchBar = props => {
return(
<div>
<input className=»searchBar» type=»text» placeholder=»search user» onChange={props.searchFunc}/>
</div>
)
}
export default SearchBar
|
Компонент списка
Этот просто перечислит имена пользователей.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import React, {Component} from ‘react’
import LoadingHOC from ‘./LoadingHOC’
import ‘../styles/main.css’
const List = (props) =>{
const{usernames} = props
return(
<ul>
{usernames.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
)
}
export default LoadingHOC(List)
|
Здесь мы снова использовали метод map
чтобы получить каждый элемент в массиве и создать из него элемент <li>
. Обратите внимание, что когда вы используете map
для создания списка элементов, вам нужно использовать key
чтобы React отслеживал каждый элемент списка.
Обратите внимание, что мы обернули List
другим компонентом с именем LoadingHOC
перед его экспортом. Вот как работают компоненты высшего порядка (HOC).
Здесь мы передали наш компонент в качестве аргумента другому компоненту перед его экспортом. Таким образом, этот компонент LoadingHOC
будет LoadingHOC
наш компонент новыми функциями.
Компонент LoadingHOC
Как я кратко объяснил ранее, HOC принимает компонент в качестве входных данных, а затем экспортирует расширенную версию входного компонента.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import React, {Component} from ‘react’
import spinner from ‘../spinner.gif’
const LoadingHOC = (WrappedState) =>{
return(
class LoadingHOC extends Component{
render(){
return this.props.usernames.length === 0 ?
}
}
)
}
export default LoadingHOC
|
Внутри HOC мы можем получить прямой доступ к реквизиту входного компонента. Поэтому мы просто проверяем, равна ли длина имени usernames
prop 0 или нет. Если оно равно 0 , это означает, что данные еще не получены, поскольку по умолчанию это пустой массив. Таким образом, мы просто показываем GIF с блесной, который мы импортировали В противном случае мы просто показываем сам компонент ввода.
Он импортирован, чтобы не забыть передать любые реквизиты и состояния обратно компоненту ввода с помощью оператора распространения. В противном случае ваш компонент будет лишен их.
CSS-файл
Ниже вы можете найти файл CSS, характерный для этого примера.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
body, html {
-webkit-font-smoothing: antialiased;
margin: 0;
padding: 0;
background-color: #f1f1f1;
font-family: ‘Raleway’, sans-serif;
-webkit-text-size-adjust: 100%;
}
body {
display: flex;
justify-content: center;
font-size: 1rem/16;
margin-top: 50px;
}
li, ul {
list-style: none;
margin: 0;
padding: 0;
}
ul {
margin-top: 10px;
}
li {
font-size: 0.8rem;
margin-bottom: 8px;
text-align: center;
color: #959595;
}
li:last-of-type {
margin-bottom: 50px;
}
.Card {
font-size: 1.5rem;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
border-radius: 10px;
background-color: white;
box-shadow: 0 5px 3px 0 #ebebeb;
}
.header {
position: relative;
font-size: 20px;
margin: 12px 0;
color: #575757;
}
.header::after {
content: »;
position: absolute;
left: -50%;
bottom: -10px;
width: 200%;
height: 1px;
background-color: #f1f1f1;
}
.searchBar {
text-align: center;
margin: 5px 0;
border: 1px solid #c4c4c4;
height: 20px;
color: #575757;
border-radius: 3px;
}
.searchBar:focus {
outline-width: 0;
}
.searchBar::placeholder {
color: #dadada;
}
.isLoading {
margin: 30px 0;
width: 150px;
filter: opacity(0.3);
}
|
Вывод
В этом уроке мы кратко рассмотрели API генератора случайных пользователей как источник случайных данных. Затем мы извлекли данные из конечной точки API и реструктурировали результаты в новом объекте JavaScript с помощью метода map
.
Следующим шагом было создание функции фильтрации с помощью filter
и методов. Наконец, мы создали два разных компонента и усовершенствовали один из них компонентом высшего порядка (HOC), введя индикатор загрузки, когда данных еще нет.
За последние пару лет популярность React возросла. На самом деле, у нас есть ряд товаров на Envato Market, которые можно приобрести, просмотреть, внедрить и так далее. Если вы ищете дополнительные ресурсы по React, не стесняйтесь проверить их .