#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
5 месяцев назад
Добрый день, у меня вопрос связан с тем что я решил переписать ваш курс интернет магазин на реак ридакс с рамда(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
4 месяцев назад
Добрый день. Так сложно сказать, но у вас newValues = Object.assign присваивает в обьект ключи по индексу, а не idшники(как делает R.indexBy), возможно в этом проблема. Если выводит failure то дебажте, где код падает в failure и почему.
016
1год назад назад
Добрый день! Заглянул в документацию по 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
1год назад назад
Добрый день. Рекомендую смотреть тесты для лучшего понимания 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
1год назад назад
Пытаюсь написать на рамде функцию которая будет изменять имя ключа в объекте. Но кажется уже лучше бы на обычном js накостылял бы) И всё ради эластика
monsterlessons
1год назад назад
Это же просто удалить и добавить. В этом вам поможет assoc и dissoc. R.compose( R.assoc('b', '1'), R.dissoc('a') )({a: 1})
Moonlight
1год назад назад
если бы всё так просто, нужно сохранять вложенные свойства объекта, в таком случае они удалятся) Нашел полезное дополнение Ramda Adjunct. https://github.com/ramda/ramda/wiki/Cookbook#rename-keys-of-an-object вот что они предлагают, очень спасло кстате
monsterlessons
1год назад назад
Отлично, что нашли. Значит у вас не самый стандартный кейс просто.
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
2 лет назад
Доброе время суток. Просмотрел все ваши видео по Ramda.jS, записал всё в блокнот)) Сейчас юзаю ReacJS/Redux/RamdaJS) Спасибо огромное за труды!
monsterlessons
2 лет назад
Добрый день. На здоровье. Рад что видео помогли.
Moonlight
1год назад назад
тож самое, советую еще комбо redux-act + redux-saga код редакса будет выглядеть короче и проще с этим
Alex Panchuk
2 лет назад
Просмотрел весь курс. Очень понравилось. Отлично подобран материал и подача на уровне. Когда сам пробовал разбираться с ramda по документации, получалось значительно тяжелее. Спасибо!
monsterlessons
2 лет назад
Спасибо большое. Очень приятно.