#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')

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

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

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
bersh
1 месяц назад назад
Добрый день, у меня вопрос связан с тем что я решил переписать ваш курс интернет магазин на реак ридакс с рамда(https://monsterlessons.com/project/lessons/podgotovka-dannyh-dlya-stranicy-tovarov) на нативный js, подскажите в чем разница между этими строчками ? const newValues = Object.assign({}, {...payload}) return Object.assign({}, {...state}, {...newValues}) и const newValues = R.indexBy(R.prop('id'), payload) return R.merge(state, newValues) в консолки выводит одинаковые результаты но телефоны не отрисовываются и отрабатывает action FAILURE Может дело в том что я не переписал phonePage(
monsterlessons
1 месяц назад назад
Добрый день. Так сложно сказать, но у вас newValues = Object.assign присваивает в обьект ключи по индексу, а не idшники(как делает R.indexBy), возможно в этом проблема. Если выводит failure то дебажте, где код падает в failure и почему.
016
10 месяцев назад
Добрый день! Заглянул в документацию по 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
10 месяцев назад
Добрый день. Рекомендую смотреть тесты для лучшего понимания 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
12 месяцев назад
Пытаюсь написать на рамде функцию которая будет изменять имя ключа в объекте. Но кажется уже лучше бы на обычном js накостылял бы) И всё ради эластика
monsterlessons
12 месяцев назад
Это же просто удалить и добавить. В этом вам поможет assoc и dissoc. R.compose( R.assoc('b', '1'), R.dissoc('a') )({a: 1})
Moonlight
12 месяцев назад
если бы всё так просто, нужно сохранять вложенные свойства объекта, в таком случае они удалятся) Нашел полезное дополнение Ramda Adjunct. https://github.com/ramda/ramda/wiki/Cookbook#rename-keys-of-an-object вот что они предлагают, очень спасло кстате
monsterlessons
11 месяцев назад
Отлично, что нашли. Значит у вас не самый стандартный кейс просто.
Krot TV
1год назад назад
Подскажи пж, как можно использовать R.lens, когда есть вложенность. Например: const user = { name:'ivan', data:{ age:18, } } Как обратится к age, или это не имеет смысла делать через R.lens?
monsterlessons
1год назад назад
Смотря, что вы хотите сделать. Зависит от задачи. Иногда R.lens подходит, иногда нет. В простых вариантах R.assocPath, если вам нужно обновить значение или R.path если прочитать.
Krot TV
1год назад назад
Ага, понял, спасибо)
Aleksandr Polyakh
1год назад назад
Доброе время суток. Просмотрел все ваши видео по Ramda.jS, записал всё в блокнот)) Сейчас юзаю ReacJS/Redux/RamdaJS) Спасибо огромное за труды!
monsterlessons
1год назад назад
Добрый день. На здоровье. Рад что видео помогли.
Moonlight
12 месяцев назад
тож самое, советую еще комбо redux-act + redux-saga код редакса будет выглядеть короче и проще с этим
Alex Panchuk
2 лет назад
Просмотрел весь курс. Очень понравилось. Отлично подобран материал и подача на уровне. Когда сам пробовал разбираться с ramda по документации, получалось значительно тяжелее. Спасибо!
monsterlessons
2 лет назад
Спасибо большое. Очень приятно.