Table of Contents
Refs
Рефы дают возможность получить доступ к DOM-узлам или React-элементам, созданным в рендер-методе
Когда использовать рефы Ситуации, в которых использования рефов является оправданным:
Управление фокусом, выделение текста или воспроизведение медиа.
Императивный вызов анимаций.
Интеграция со сторонними DOM-библиотеками.
Избегайте использования рефов в ситуациях, когда задачу можно решить декларативным способом.
Например, вместо того чтобы определять методы
open()
иclose()
в компонентеDialog
, лучше передавать ему пропisOpen
.
Создание рефов
Рефы создаются с помощью React.createRef()
и прикрепляются к React-элементам через ref атрибут. Обычно рефы присваиваются свойству экземпляра класса в конструкторе, чтобы на них можно было ссылаться из любой части компонента.
Доступ к рефам
Когда реф передаётся элементу в методе render
, ссылка на данный узел доступна через свойство рефа current
.
const node = this.myRef.current;
Значение рефа отличается в зависимости от типа узла:
- Когда атрибут ref используется с HTML-элементом, свойство
current
созданного рефа в конструкторе с помощью React.createRef() получает соответствующий DOM-элемент. - Когда атрибут ref используется с классовым компонентом, свойство
current
объекта-рефа получает экземпляр смонтированного компонента.
important
Нельзя использовать ref
атрибут с функциональными компонентами, потому что
для них не создаётся экземпляров.
React присвоит DOM-элемент свойству
current
при монтировании компонента и присвоит обратно значениеnull
при размонтировании. Обновление свойстваref
происходит перед вызовом методовcomponentDidMount
иcomponentDidUpdate
.
Почитать 📚
List & Keys
Мы можем создать коллекцию элементов и встроить её в JSX
с помощью фигурных скобок {}
.
К примеру, напишем простой компонент NumberList
.
Пройдём по массиву numbers, используя функцию JavaScript map()
, и вернём элемент <li
> в каждой итерации. Получившийся массив элементов сохраним в listItems:
const NumberList = () => {const numbers = [1, 2, 3, 4, 5];const listItems = numbers.map((number) => <li>{number}</li>);return <ul>{listItems}</ul>;};
Когда вы запустите данный код, то увидите предупреждение о том, что у каждого элемента массива должен быть ключ (key)
.
important
«Ключ» — это специальный строковый атрибут, который нужно указывать при создании списка элементов. Мы обсудим, почему это важно, ниже на странице.
Чтобы исправить проблему с неуказанными ключами, добавим каждому элементу в списке
атрибут key
.
const NumberList = () => {const numbers = [1, 2, 3, 4, 5];const listItems = numbers.map((number) => <li key={number}>{number}</li>);return <ul>{listItems}</ul>;};
Keys
Ключи помогают React определять, какие элементы были изменены, добавлены или удалены. Их необходимо указывать, чтобы React мог сопоставлять элементы массива с течением времени:
note
Лучший способ выбрать ключ — это использовать строку, которая будет явно
отличать элемент списка от его соседей. Чаще всего вы будете использовать ID
из ваших данных как ключи:
const users = [{name: "Alex",id: 1,},{name: "John",id: 2,},{name: "Bob",id: 3,},];const User = (props) => {return (<li><span>{props.id}</span>--<span>{props.name}</span></li>);};class UserList extends React.Component {render() {return (<ul>{this.props.users.map((user) => (<li key={user.id}><span>{user.id}</span>--<span>{user.name}</span></li>))}</ul>);}}
Когда у вас нет заданных ID для списка, то в крайнем случае можно использовать индекс элемента как ключ:
const todoItems = todos.map((todo, index) => (// Делайте так, только если у элементов массива нет заданного ID<li key={index}>{todo.text}</li>));
Ключи должны быть уникальными среди соседних элементов
Ключи внутри массива должны быть уникальными только среди своих соседних элементов. Им не нужно быть уникальными глобально. Можно использовать один и тот же ключ в двух разных массивах.
Ключи служат подсказками для React, но они никогда не передаются в ваши компоненты. Если в компоненте нужно то же самое значение, то передайте его явно через проп с другим именем:
const content = posts.map((post) => (<Post key={post.id} id={post.id} title={post.title} />));
В примере выше компонент Post может прочитать значение props.id, но не props.key.
Почитать
Практика
- UserList
Используя код https://codesandbox.io/s/react-keys-and-refs-64hvo?file=/src/UserList.js
- Исправить все warning в консоли
- Добавить кнопку
Reset
поле поиск должно быть очищено - Добавить дополнительную кнопку
Add to Top
, по клику на которую юзер должен добавляться вверх - Добавить дополнительную кнопку
Add to Bottom
, по клику на которую юзер должен добавляться вниз - Добавить кнопку
remove
для каждого юзера, по клюку на которую юзер должен быть удален и список перерисован с актуальными данными
Select user Добавить возможность по клику на юзера (элемент списка) подсвечивать выбранного юзера (можно добавить className active ),
Выбранный юзер может быть только один
RandomAdvice
Написать Родительский комопнент для
RandomAdvice
который должен иметь кнопкуRefresh Advice
, по клику на которуюRandomAdvice
component должен быть перерисовна с новымadvice
Код RandomAdvice должен быть не тронут
ДЗ 🏡
GithubUsers
Использую API github https://api.github.com/users
Написать комопнент который будет запрашивать юзеров с гитхаб и выводить их списком.
- Показывать
Loading
пока данные загружаються с сервера - Показывать сообщение об ошибке если запрос с сервера вернул ошибку
Searching advice
Использую API https://api.adviceslip.com/
Написать компонент для поиск advice
- показывать loading пока данные загружаються с сервера
- показывать сообщение об ошибке если запрос с сервера вернул ошибку
- показывать
No found
если запрос с сервера вернул пустой результат - добавить кнопку
clear
рядом сinput
по клику на которую поле поиска должно быть сброшено
Добавить функцию debounce если поиск срабатывает непосредственно после измененения значения в input
Если поиск работает по клику на кнопку search
, debounce
не нужен