Обсуждение id для массива объектов в React


Как вы уже знаете, в массиве объектов должны присутствовать уникальные id. Давайте разберемся, откуда они берутся.

Массивы объектов могут иметь два происхождения: либо они присланы нам сервером, либо сгенерированы на клиенте (то есть в браузере).

Данные, присланные нам сервером, как правило хранились там в базе данных. Базы данных (БД) бывают вида SQL (например, mySQL, PostgreSQL) или NoSQL (например, MongoDB).

SQL базы данных, как правило имеют числовые id, автоматически расставляемые базой данных по возрастанию.

NoSQL базы данных, как правило, имеют id, представляющие собой случайные уникальные строки. Предполагается, что эти строки не имеют совпадений (коллизий) у двух элементов массива.

Уникальность id достигается за счет достаточно большой длины случайных строк - настолько больших, что вероятность совпадения двух строк будет близка в нулю.

При этом, чем больше данных в БД, тем больше вероятность коллизии. Задача программиста состоит в том, чтобы заранее прикинуть объем данных и определить оптимальную длину случайных строк, чтобы вероятность коллизий была минимальна (достаточно мала, чтобы считаться приемлемой).

Проблемы с добавлением данных
Пусть из SQL базы данных нам пришел следующий массив объектов:

const prods = [
{id: 1, name: 'product1', cost: 100},
{id: 2, name: 'product2', cost: 200},
{id: 3, name: 'product3', cost: 300},
];
Как вы видите, id нумеруются по порядку. Однако, нам следует учитывать, что числа могут иметь пропуски, к примеру, после 3-го может сразу идти 5-тый или 6-той. Из-за этого наш клиентский скрипт не может знать, какой будет следующий id (в нашем случае это не обязательно 4).

Новые id создаются базой данных сервера. Это может вызвать некоторые проблемы при работе на клиенте. Суть в следующем: представим, что с помощью формы мы добавили новый элемент в наш массив. Однако, мы не можем просто взять и добавить данные из формы - ведь мы не знаем какой id будет у нового элемента!

Нам нужно будет отправить запрос на сервер, чтобы он дал нам следующий по порядку id, и только затем добавить элемент в наш массив объектов. Это вызовет задержку с отображением данных на экране: пока данные придут на сервер, пока сервер пришлет нам их обратно - пройдет некоторое время.

Id в виде строк и добавление
Пусть теперь массив объектов имеет следующий вид:

const prods = [
{id: 'GYi9G_uC4gBF1e2SixDvu', name: 'product1', cost: 100},
{id: 'IWSpfBPSV3SXgRF87uO74', name: 'product2', cost: 200},
{id: 'JAmjRlfQT8rLTm5tG2m1L', name: 'product3', cost: 300},
];
Как вы видите, теперь наши id представляют собой случайные уникальные строки. Такой массив мог быть получен с NoSQL базы данных, либо просто сгенерирован на клиенте.

Опять представим себе ситуацию с добавлением в этот массив данных формы. В этом случае задержки не возникнет - при добавлении данных мы просто сгенерируем случайную строку, которая и будет новым id.

Генерация id
К счастью, нам не нужно самостоятельно придумывать код, генерирующий случайные id. К нашим услугам есть готовые библиотеки. Например, библиотека nanoid, генерирующая случайные строки, либо библиотека react-uuid, генерирующая UUID.

Функция для генерации id
Так как используемая библиотека для генерации id может быть разная, далее в уроках я буду использовать следующую функцию-оболочку:

function id() {
// тут генерация id
}
Предполагается, что эта функция генерирует id удобным вам способом.

Использование функции id()
Мы можем использовать нашу функцию следующим образом при объявлении массива объектов:

const prods = [
{id: id(), name: 'product1', cost: 100},
{id: id(), name: 'product2', cost: 200},
{id: id(), name: 'product3', cost: 300},
];

Неправильное использование функции id()
Неправильно генерировать id прямо в атрибуте, вот так:

const res = prods.map(function(prod) {
return <p key={id()}>
<span>{prod.name}</span>
<span>{prod.cost}</span>
</p>;
});
Причины этого будут вам понятны в следующих уроках. Пока просто имейте ввиду, что так делать неправильно и никогда так не делайте.