Обʼєкт місцезнаходження

При переміщенні по застосунку у стек історії записуються обʼєкти про розташування (location). Вони мають стандартний набір властивостей, які зберігають повну інформацію про URL.

{
  pathname: string;
  search: string;
  hash: string;
  state: any;
  key: string;
}

Що зберігається у цьому обʼєкті:

  • pathname - рядок, який містить частину URL від початкового / і до символу ?.

  • search - містить весь рядок запиту. Якщо параметри відсутні, то значенням буде порожній рядок.

  • hash - рядок, який містить частину URL після рядка запиту та символу #, за яким слідує ідентифікатор фрагмента URL-адреси. Якщо ідентифікатор фрагмента відсутній, значенням буде порожній рядок.

  • state - довільне значення, яке містить додаткову інформацію, пов'язану з розташуванням, але не відображається в URL-адресі. Це поле використовують розробники для передачі даних між маршрутами.

  • key - унікальний рядок ідентифікатор, пов'язаний із цим локейшеном. Службова властивість, значення якої задається автоматично для кожного нового запису в історії навігації.

Наприклад, для такого URL об'єкт розташування може мати наступний вигляд:

https://mysite.com/phones?firm=apple&color=black&maxPrice=700&inStock=true#reviews

{
  "pathname": "/phones",
  "search": "?firm=apple&color=black&maxPrice=700&inStock=true",
  "hash": "#reviews",
  "state": null,
  "key": "random-browser-generated-id"
}

Хук useLocation

Хук useLocation повертає об'єкт розташування поточного URL. При навігації новими маршрутами по застосунку цей обʼєкт оновлюється. Є різні варіанти використання розташування, наприклад застосувати useEffect i, наприклад надсилати дані на сервіс статистики при оновленні локації.

src/component/App.jsx
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import Analytics from "path/to/analytics-service";

const App = () => {
  const location = useLocation();

  useEffect(() => {
    Analytics.send(location);
  }, [location]);

  return <div>...</div>;
};

Властивість location.state

Уявімо, що у нас на сторінці прикладів робіт /works велика їх кількість і ми робимо пошук, наприклад за словом cafe /works?name=cafe. І нам видає список прикладів робіт, які мають тільки такий збіг у назві. При переході на сторінку якоїсь із робіт нам потрібно зберегти локацію попередньої сторінки разом із рядком запиту. І реалізувати кнопку "назад" при натисканні на яку ми не просто повернемося на сторінку /works а разом з рядком запиту /works?name=cafe.

Вище було зазначено, що в обʼєкта розташування є властивість state. З її допомогою можна передавати довільні дані при навігації з одного маршруту до іншого. Для цього в компоненті Link потрібно передати prop state, а в ньому обʼєкт із властивістю from - звідки прийшов користувач. Prop state може бути довільної структури на вибір розробника.

src/pages/Works.jsx
const Works = () => {
  return (
    <Link to="/works/verywellcafe" state={{ from: "/works?name=cafe" }}>
      Open VeryWellCafe card
    </Link>
  );
};

Тепер це значення prop state буде доступно на об'єкті розташування на маршруті куди була виконана навігація (в даному разі на компонент WorkDetails). Щоб в ньому отримати дані про поточну локацію, і локацію з якої ми прийшли, потрібно за допомогою хука useLocation отримати обʼєкт location і прочитати її властивість state.

src/pages/WorkDetails.jsx
const WorkDetails = () => {
  const location = useLocation();
  console.log(location.state); // { from: "/works?name=cafe" }

  return <Link to={location.state.from}>Return to works</Link>;
};

Але ніхто насправді на практиці не передає рядок URL маршруту у властивості from. у prop state передають одразу об'єкт location поточного маршруту.

src/pages/Works.jsx
const Works = () => {
  const location = useLocation();

  return (
    <Link to="/works/verywellcafe" state={{ from: location }}>
      Open VeryWellCafe card
    </Link>
  );
};

Коли ми перемістимося за новим роутом у властивості location.state буде посилання на об'єкт location маршруту з якого відбулася навігація.

Тепер на новій сторінці компоненту Link можна передати prop to і передати в ньому location.state.from і це буде посиланням на попередню сторінку.

src/pages/WorkDetails.jsx
const WorkDetails = () => {
  const location = useLocation();
  console.log(location.state);

  return <Link to={location.state.from}>Return to works</Link>;
};

Але уявімо ситуацію, що на сторінку продукту користувач прийшов за прямим посиланням у новій вкладинці, а не з іншої сторінки всіх робіт. В такому випадку в location.state буде null, бо на попередньому етапі ми не передали ніякого локейшена. І при натисканні на кнопку виникне помилка. В такому разі треба передбачити, що якщо немає маршруту на попередню сторінку, то перехід відбуватиметься на сторінку всіх робіт. Тобто визначимо значення porop to за замовчанням.

src/pages/WorkDetails.jsx
const WorkDetails = () => {
  const location = useLocation();
  const backLinkHref = location.state?.from ?? "/works";

  return <Link to={backLinkHref}>Return to works</Link>;
};

Розберемо синтаксис визначення посилання на сторінку назад. Тут використано оператор нульового злиття і оператор опціональної послідовності.

const backLinkHref = location.state?.from ?? "/works";

Це спрощений синтаксис тернарного оператора з такою умовою

const backLinkHref = location.state ? location.state.from : "/works";

Розібрати кнопку повернення можна на живому прикладі тут. Зміни стосуються компонентів Works і WorkDetails.

Last updated