Pull to refresh

Работа со строкой запроса в React

Reading time4 min
Views14K
Привет. Это та статья, о том пакете которого мне не хватало в работе с реактом.

image

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

Как вы это делаете сейчас


Получение значений


Как вы получаете значение со строки запроса? Я думаю примерно вот так:

const { item } = queryString.parse(props.location.search);

или если вы знакомы со URLSearchParams, то можно вот так:

const params = new URLSearchParams(props.location.search);
const item = params.get('item');

Какой вариант более предпочтительнее не совсем понятно, т.к. первый подтягивает npm пакет, но работает везде, а второй встроен в браузер, но там могут быть проблемы с IE (mozilla).

Установка значений


С получением разобрались, как-то но все таки получили точно такой же результат как и хотелось. Перейдем к установке значений. Делается это все в помощью history.push, которая принимает уже строку с уже добавлеными параметрами. К примеру так:

history.push('/path?item=my-item-data')

Для более сложных конструкций нужно будет использовать querystring:

const query = queryString.stringify({ item: "my-item-data" });
history.push(`/?${query}`);

или URLSearchParams:

const query = new URLSearchParams();
query.set("item", "my-item-data");
history.push(`/?${query}`);

Последствия


Хорошо. Не смотря на то что данные мы всегда получаем строковые (и нам нужно их парсить), так еще и наступает проблема, если мы будет ожидать цифру, а прийдет слово (пользователю не запрещено менять запрос в строке), прийдеться городить проверки, и пушить значение самому.

Больше всего боли наступает, когда нужно что бы поля запроса зависили от компонентов которые сейчас отображаються, сейчас же каждый компонент будет работать с одним глобальным стейтом, и менять его по своему усмотрению, опираясь на уже существующие значение, прийдеться для добавление не только добавлять свои значение, а еще и все остальные подгятивать, что-то типа такого:

const oldQuery = queryString.parse(location.search);
const query = queryString.stringify({ item: "my-item-data" });
history.push(`/?${{...oldQuery,  ...query}}`);

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

Еще же нужно потом очищать значние после себя, конечно history.push сделает это за вас, но куда проще не заморачиваться на этим и дать вместо вас делать это другим.

Хорошо. Что же предлагаю я?


Я думаю я сделал это за вас, и в более удобном виде. Далее пойдет речь об npm пакете
react-location-query, который, возможно, стоит вашего внимание.

Пакет реализовывает хуки и HOC-компоненты (просто обёртка над хуками), для установки правил работы параметров в поисковой строке, где мы устанавливаем значение в одном из компонентов, а можем получить в любом другом компоненте (даже выше по дереву, но не стоит так делать).

Пример


К примеру, есть страница UsersPage, а в ней компоненты UsersList и Controls. UsersList — для загрузки и отображение списка пользователей, а Controls — для установки фильтрации пользователей. Все можно представить вот так:

const UsersPage = () => {
  const [type] = useLocationField('type', 'github');

  return ...;
}

const UsersList = () => {
  const [page, setPage] = useLocationField('page', {
    type: 'number',
    initial: 1,
    hideIfInitial: true
  });
  const [limit, setLimit] = useLocationField('limit', {
    type: 'number',
    initial: 20,
    hideIfInitial: true
  });
  const [type] = useLocationField('type');

  return ...;
}

const Controls = () => {
  const [type, setType] = useLocationField('type');
 // тут можно менять поле type посредством setType
  return ...;
}

Как мы можем заметить, для полей page и limit, мы использовали объект, в котором указали следующие опции:

  • type — тип в который значение должно парситься при получении (если не передавать объект, а простое значение то тип будет зависит от типа переданого значение)
  • initial — значение по умолчанию, это же поле указывается если мы не используем объект
  • hideIfInitial — опция для указания: прятать ли значение с поисковой строки, если оно равно изначальному значение (т.е. значение по умолчанию), может пригодиться если мы показываем первую страницу пользователей, то что бы не портить вид строки лишними параметрами

Небольшое описание


Для настройки поля и его значения присутствуют и другие поля, к примеру коллбек (который возвращает новое значение) в случае невозможного парсинга значения (передали строку, а ожидали число/булевое значение). Все эти поля можно увидеть в README в на странице npm-пакета или на github

Так же небольшое описание присутствующих хуков:

  • useLocationField — хук для работы строго с одним значения
  • useLocationQuery — хук для работы со многими значениями
  • useLocationQueryExtend — хук для работы со многими значениями данные которых выходят за рамки стандартов (к примеру json)
  • useLocationClear — хук для начала работы, нужно положить в рутовый компонент (без него не будет происходить очистка полей), или не нужно ложить если там уже находиться какой-то их хуков описаных выше

Так же помимо хуков присутствуют HOC-компоненты которые являются их обёртками хуков.

Футер


Эта статья написана для того, что бы уведомить других об присутствии этого пакета. Есть еще много фишек которые я хочу туда еще имплементировать (к примеру enum значение), пока жду фидбеков и информации имеет ли этот пакет хоть немного права на жизнь или совсем ненужный.
Tags:
Hubs:
+3
Comments0

Articles