#6 Получаем глубоко вложенные поля с Ramda path

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

В этом видео мы рассмотрим как получать поля многоуровневого объекта с помощью Ramda.

Представим, что у нас есть два юзера с разными полями, которые мы получили от бекенда.

const bill = {
  nickname: 'Bill',
  country: 'UK',
  personal: {
    profile: {
      name: 'Bill',
      surname: 'Williams',
      age: 20
    }
  }
}

const mike = {
  nickname: 'Mike',
  country: 'US',
  personal: {}
}

Как вы видите, у юзера Mike не заполнена персональная информация в профиле.

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

И для получения фамилии юзера мы написали вот такой код.

const getSurname = user => user.personal.profile.surname

console.log(getSurname(bill))
console.log(getSurname(mike))

И все работает. Но когда нам пришел юзер Mike, у которого нет этого поля, то у нас код упал. Мы получили ошибку "Cannot read property surname of undefined".

Мы понимаем, что нам необходима проверка на то, что у нас есть поле profile. Но мы сразу думаем: "А что, если у нас вообще user будет null? Или поле personal придет не обьект, а null? Нужно же покрыть все эти кейсы".

И мы пишем вот такой код

const getSurname = user =>
  user &&
  user.personal &&
  user.personal.profile &&
  user.personal.profile.surname

Теперь, если у нас нет какого-то поля, то мы получаем undefined. Но этот код выглядит очень грустно.

В Ramda есть специальный метод path, который проверяет всю цепочку самостоятельно. Первым аргументом мы передаем массив цепочки, а вторым объект, на который хотим вызвать цепочку.

const getSurname = user => R.path(['personal', 'profile', 'surname'], user)

Так как метод каррирован, то мы можем сделать функцию point free.

const getSurname = R.path(['personal', 'profile', 'surname'])

Как вы видите, все работает как и раньше, но код намного лаконичнее.

Что делать, когда у нас surname undefined, а мы хотим вернуть строку "not set", чтобы на фронтенде было видно, что surname не задан?

Для этого, мы можем использовать метод pathOr, в который первым аргументом задаем дефолтное значение, если поле не найдено.

const getSurname = R.pathOr('not set', ['personal', 'profile', 'surname'])

Теперь в случае с Mike, мы получаем строку "not set".

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

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
016
5 месяцев назад
Добрый день, Monster! Небольшой вопрос. Согласно доктрине фунциональности, да и для пользы дела, в строке const getSurname = R.pathOr('not set', ['personal', 'profile', 'surname']) было бы лучше для возврата задавать не строку 'not set', а нами придуманную функцию на подобный поворот событий. Я сомневаюсь, что об этом ни кто до меня не подумал, - такой вариант существует?
monsterlessons
5 месяцев назад
Добрый день. Звучит логично, но pathOr так не работает.Прийдется делать композицию, если хочется вызвать функцию R.compose( R.when(R.isNull, doSomething) R.pathOr(null, ['personal']) )
Valerii Kuzivanov
1год назад назад
а в _lodash есть подобное path и pathOr ? Не нашел в доках, мож называются по другому
monsterlessons
1год назад назад
В lodash есть только аналог path _.get(object, ['a', '0', 'b', 'c']) pathOr нет. Lodash вообще бедноват на методы)