#11 Изменение полей объекта с Ramda lenses

poster
В этом видео мы разберем такую тему как Ramda lenses.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы разберем такую тему, как линзы.

Представим себе, что у нас есть объект user с полями firstName и lastName.

const user = {
  name: 'John',
  surname: 'Flint'
}

И теперь, мы можем создать линзу.

const nameLens = R.lens(R.prop('name'), R.assoc('name'))

Мы создали линзу с помощью R.lens и передали в нее сеттер и геттер для поля name в объекте. То есть, мы описываем то, как получить какое-то поле и как его обновить.

Теперь мы можем, передав в линзу любой объект, знать, что она будет работать именно с полем name.

Давайте попробуем.

В Ramda есть несколько специальных методов для работы с линзами.

Для того, чтобы вызвать геттер, мы можем использовать R.view.

const result = R.view(nameLens, user)
console.log('result')

То есть, при вызове на объект user, у линзы вызвался геттер и мы получили наше поле.

Точно также мы можем вызывать сеттер, чтобы обновить имя.

const result = R.set(nameLens, 'Alex', user)

Мы вызвали set и передали туда линзу и новое имя. В результате, мы получили новый объект с измененным именем.

Обратите внимание, что данные не мутируются.

console.log('user', user)
console.log('result', result)

Представим, что нам нужно у объекта прочитать поле name, сделать все буквы большими и записать результат в новый объект.

С линзой мы можем написать код вот так

const nameLens = R.lens(R.prop('name'), R.assoc('name'))

const name = R.view(nameLens, user)
const upperName = R.toUpper(name)
const result = R.set(nameLens, upperName, user)
console.log('result', result)

То есть мы читаем линзу, вызываем toUpper на результат и обновляем линзу.

Если мы посмотрим в браузер, то все работает.

Но есть возможность написать этот код намного более лаконично.

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

const result = R.over(nameLens, R.toUpper, user)

И результат будет точно таким же.

И, напоследок, давайте напишем наше объявление линзы более сокращенно. Так как R.prop и R.assoc - это самая часто используемая линза, то для нее есть синтаксический сахар.

Мы можем написать

const nameLens = R.lensProp('name')

И все будет работать как и раньше.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
016
5 месяцев назад
Добрый день! Заглянул в документацию по Ramda на его сайте https://ramdajs.com. Все хорошо, но не понятна логика схем. Например, у R.lens дано описание: (s → a) → ((a, s) → s) → Lens s a Lens s a = Functor f => (a → f a) → s → f s Мозги уже вывернул, но догадаться никак не могу. ) Что подразумевается под s, a, разное количество сегментов... Моя благодарность.
monsterlessons
5 месяцев назад
Добрый день. Рекомендую смотреть тесты для лучшего понимания https://github.com/ramda/ramda/blob/master/test/lenses.js Линза чаще всего используется для изменения глубоко вложеных данных var xLens = R.lens(R.prop('x'), R.assoc('x')); Здесь мы создаем линзу описывая getter и setter. R.view(xLens, {x: 1, y: 2}); //=> 1 Используя view мы вызывем геттер R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2} Используя set мы вызываем сеттер R.over(xLens, R.negate, {x: 1, y: 2}); //=> {x: -1, y: 2} R.over это короткая запись для прочитать и изменить.
Moonlight
8 месяцев назад
Пытаюсь написать на рамде функцию которая будет изменять имя ключа в объекте. Но кажется уже лучше бы на обычном js накостылял бы) И всё ради эластика
monsterlessons
8 месяцев назад
Это же просто удалить и добавить. В этом вам поможет assoc и dissoc. R.compose( R.assoc('b', '1'), R.dissoc('a') )({a: 1})
Moonlight
7 месяцев назад
если бы всё так просто, нужно сохранять вложенные свойства объекта, в таком случае они удалятся) Нашел полезное дополнение Ramda Adjunct. https://github.com/ramda/ramda/wiki/Cookbook#rename-keys-of-an-object вот что они предлагают, очень спасло кстате
monsterlessons
7 месяцев назад
Отлично, что нашли. Значит у вас не самый стандартный кейс просто.
Krot TV
11 месяцев назад
Подскажи пж, как можно использовать R.lens, когда есть вложенность. Например: const user = { name:'ivan', data:{ age:18, } } Как обратится к age, или это не имеет смысла делать через R.lens?
monsterlessons
11 месяцев назад
Смотря, что вы хотите сделать. Зависит от задачи. Иногда R.lens подходит, иногда нет. В простых вариантах R.assocPath, если вам нужно обновить значение или R.path если прочитать.
Krot TV
11 месяцев назад
Ага, понял, спасибо)
Aleksandr Polyakh
11 месяцев назад
Доброе время суток. Просмотрел все ваши видео по Ramda.jS, записал всё в блокнот)) Сейчас юзаю ReacJS/Redux/RamdaJS) Спасибо огромное за труды!
monsterlessons
11 месяцев назад
Добрый день. На здоровье. Рад что видео помогли.
Moonlight
8 месяцев назад
тож самое, советую еще комбо redux-act + redux-saga код редакса будет выглядеть короче и проще с этим
Alex Panchuk
1год назад назад
Просмотрел весь курс. Очень понравилось. Отлично подобран материал и подача на уровне. Когда сам пробовал разбираться с ramda по документации, получалось значительно тяжелее. Спасибо!
monsterlessons
1год назад назад
Спасибо большое. Очень приятно.