Полное руководство по React Router v6. Часть 3 - Управление навигацией

год назад·5 мин. на чтение

В этой статье рассмотрим, как перемещаться между роутами. Как добавить ссылки, как перейти по ссылке программно, как передать данные при переходе.

Серия статей о React Router v6 состоит из 4 частей.
  1. Основы React Router
  2. Продвинутые определения маршрутов
  3. Управление навигацией (рассматривается в этой статье)
  4. Подробно о роутерах
В этой статье рассмотрим следующие темы.
  1. Навигация по ссылкам
  2. Ручная навигация
  3. Передача данных при навигации

Навигация по ссылкам

Навигация по ссылкам - это самая простая и распространенная форма навигации. Мы уже видели самую простую форму навигации по ссылкам с помощью компонента Link.
<Link to="/">Home</Link>
<Link to="/books">Books</Link>
Однако эти компоненты Link могут стать немного сложнее. Например, у вас могут быть абсолютные ссылки, подобные приведенным выше ссылкам, или у вас могут быть ссылки, относящиеся к текущему отображаемому компоненту.
<Link to="/">Home</Link>
<Link to="../">Back</Link>
<Link to="edit">Edit</Link>
Например, представьте, что мы находимся в маршруте /books/3 с приведенными выше ссылками. Первая ссылка приведет к / маршруту, так как это абсолютный маршрут. Любой маршрут, начинающийся с /, является абсолютным маршрутом. Вторая ссылка приведет к маршруту /books, так как это относительная ссылка, которая поднимается на один уровень вверх от /books/3 к /books. Наконец, наша третья ссылка перейдет на страницу /books/3/edit, так как она добавит путь к пропсу to в конец текущей ссылки, поскольку это относительная ссылка.
Помимо пропса to, есть также 3 других пропса, которые важны для компонента Link.

replace

Проп replace имеет логическое значение, которое, если установить в true, приведет к тому, что эта ссылка заменит текущую страницу в истории браузера. Представьте, что у вас есть следующая история браузера.
/
/books
/books/3
Если вы нажмете на ссылку, ведущую на страницу /books/3/edit, но у нее проп replace имеет значение `trueё, ваша новая история будет выглядеть следующим образом.
/
/books
/books/3/edit
Страница, на которой вы находились в данный момент, была заменена новой страницей. Это означает, что если вы нажмете кнопку «Назад» на новой странице, вы вернетесь на страницу /books, а не на страницу /books/3.

reloadDocument

Проп reloadDocument также является логическим. Если задано значение true, компонент Link будет действовать как обычный тег <a> и выполнять полное обновление страницы при навигации вместо того, чтобы просто повторно отображать содержимое внутри компонента Routes.

state

Финальный проп называется state. Этот проп позволяет передавать данные вместе с Link, которая не отображается нигде в URL-адресе. Рассмотрим эту возможность более подробно, когда будем говорить о навигационных данных.

NavLink

Компонент NavLink работает точно так же, как компонент Link, но он предназначен специально для отображения активных состояний ссылок, например, в панелях навигации. По умолчанию, если проп to у NavLink совпадает с URL-адресом текущей страницы, к ссылке будет добавлен класс active, который можно использовать для стилизации. Если этого недостаточно, можно передать функцию с параметром isActive в className, или в свойства style, или в качестве дочерних элементов NavLink.
<NavLink
  to="/"
  style={({ isActive }) => ({ color: isActive ? "red" : "black" })}
>
  Home
</NavLink>
Еще NavLink имеет проп end, который используется для помощи во вложенной маршрутизации. Например, если мы находимся на странице /books/3, это означает, что мы визуализируем компонент Book, который вложен в наш маршрут /books. Это означает, что если у нас есть NavLink с to установленным в /books, он будет считаться активным. Это связано с тем, что NavLink считается активным, если URL-адрес to совпадает с пропсом to NavLink или если текущий Route находится внутри родительского компонента c path, который совпадает с пропсом to компонента NavLink. Если вы не хотите такое поведение по умолчанию, вы можете установить проп end в true, чтобы URL-адрес страницы точно соответствовал пропсу to NavLink.

Ручная навигация

Иногда нужно вручную перемещаться на основе таких вещей, как отправка формы или отсутствие доступа к определенной странице. Для таких случаев можно использовать либо компонент Navigate, либо хук useNavigation.

Компонент Navigate

Компонент Navigate — это очень простой компонент, который при визуализации автоматически перенаправляет пользователя на значение пропса to компонента.
<Navigate to="/" />
Компонент Navigate имеет те же пропсы, что и компонент Link, таким образом вы можете передать ему to, replace и state.

Хук useNavigation

Хук useNavigation представляет собой хук, который не принимает никаких параметров и возвращает одну функцию navigate, которую вы можете использовать для перенаправления пользователя на определенные страницы. Эта функция navigate принимает два параметра. Первый параметр — это местоположение to, в которое вы хотите перенаправить пользователя, а второй параметр — это объект, который может иметь ключи для replace и state.
const navigate = useNavigate()

function onSubmit() {
  // Отправка значения формы
  navigate("/books", { replace: true, state: { bookName: "Fake Title" }})
}
Приведенный выше код перенаправит пользователя на маршрут /books. Он также заменит текущий маршрут в истории и передаст некоторую информацию через state. Другой способ, которым вы можете использовать функцию navigate, — передать ей число. Это позволит вам имитировать нажатие кнопки вперед/назад.
navigate(-1) // Перемещает назад на одну страницу в истории
navigate(-3) // Перемещает назад на три страницу в истории
navigate(1) // Перемещает вперед на одну страницу в истории

Передача данных при навигации

Наконец, пришло время поговорить о передаче данных между страницами. Существует 3 основных способа передачи данных между страницами.
  1. Динамические параметры
  2. Параметры поиска
  3. Данные состояния/местоположения

Динамические параметры

Мы уже говорили о том, как использовать динамические параметры в URL-адресах с помощью хука useParams. Это лучший способ обработки передаваемой информации, такой как идентификаторы.

Параметры поиска

Параметры поиска — это все параметры, которые идут после ? в URL-адресе (?name=Kyle&age=27). Для работы с параметрами поиска необходимо использовать хук useSearchParams, который работает очень похоже на useState.
import { useSearchParams } from "react-router-dom"

export function SearchExample() {
  const [searchParams, setSearchParams] = useSearchParams({ n: 3 })
  const number = searchParams.get("n")

  return (
    <>
      <h1>{number}</h1>
      <input
        type="number"
        value={number}
        onChange={e => setSearchParams({ n: e.target.value })}
      />
    </>
  )
}
В этом примере у нас есть инпут, который по мере ввода будет обновлять поисковую часть нашего URL-адреса. Например, если наш ввод имеет значение 32, наш URL-адрес будет выглядеть так: http://localhost:3000?n=32. Хук useSearchParams принимает начальное значение, как useState, и в нашем случае наше начальное значение n равно 3. Затем этот хук возвращает два значения. Первое значение - это все наши параметры поиска, а второе значение - это функция для обновления наших параметров поиска. Функция set просто принимает один аргумент, который является новым значением параметров поиска. Однако первое значение, содержащее параметры поиска, немного более запутанно. Это связано с тем, что это значение относится к типу URLSearchParams. Вот почему нам нужно использовать синтаксис .get в строке 5 выше.

Данные состояния/местоположения

Вся эта информация в этом случае будет доступна через хук useLocation. Использовать этот хук очень просто, так как он возвращает одно значение и не принимает никаких параметров.
const location = useLocation()
Если у нас есть следующий URL http://localhost/books?n=32#id то возвращаемое значение useLocation будет выглядеть следующим образом.
{
  pathname: "/books",
  search: "?n=32",
  hash: "#id",
  key: "2JH3G3S",
  state: null
}
Этот объект местоположения содержит всю информацию, относящуюся к нашему URL-адресу. Он также содержит уникальный ключ, который можно использовать для кэширования, если вы хотите кэшировать информацию, когда пользователь нажимает кнопку «Назад», чтобы вернуться на страницу. Вы также заметите, что у нас есть проп state, возвращаемое из useLocation. Эти данные состояния могут быть любыми и передаются между страницами без сохранения в URL-адресе. Например, если вы нажмете на Link, которая выглядит следующим образом:
<Link to="/books" state={{ name: "Kyle" }}>
тогда значение состояния в объекте location будет установлено в { name: "Kyle" }. Это может быть очень полезно, если, например, вы хотите отправлять простые сообщения между страницами, которые не должны храниться в URL-адресе. Хорошим примером этого может быть что-то вроде сообщения об успешном завершении, которое отправляется на страницу, на которую вы перенаправляетесь после создания новой книги.

12 популярных вопросов с ответами на JavaScript собеседовании

2 года назад·4 мин. на чтение

Эта статья предназначена для junior разработчиков, которые хотят получить свою первую работу в качестве JavaScript разработчиков.

1. Что такое JavaScript и для чего он используется?

Javascript - это высокоуровневый, динамичный и интерпретируемый язык программирования, широко используемый для многих сред, таких как интерфейс веб-сайтов, backend службы, desktop и мобильные приложения. Но чаще всего JavaScript используется для создания динамических и интерактивных веб-сайтов.

2. Что такое замыкание в JavaScript?

Замыкание — это функция, которая имеет доступ к переменным своей внешней функции. Это важно, потому что это позволяет внутренней функции «запоминать» переменные из своей внешней области, поэтому она может продолжать получать к ним доступ и манипулировать ими даже после того, как внешняя функция была завершена.
function outerFunction(x) {
  return function innerFunction(y) {
    return x + y;
  };
}

const add5 = outerFunction(5);
console.log(add5(3)); // 8

3. Как this работает в JavaScript?

this важное ключевое слово в JavaScript. Его значение определяется тем, как вызывается функция. Его можно задать явно с помощью call(), apply() или bind(). По умолчанию его значение внутри функции устанавливается в глобальный объект (в браузере это объект window), за исключением того, когда функция вызывается как метод объекта. В этом случае this указывает на объект, методом которого он является.

4. Что такое поднятие (hoisting) в JavaScript?

В JavaScript поднятие — это поведение, при котором переменные и объявления функций в памяти автоматически перемещаются в верхнюю часть своей области. Что это значит? Ну, это означает, что эти переменные могут быть использованы до того, как они будут объявлены, и объявления функций также могут быть вызваны до их определения.

5. В чем разница между var, let и const?

  • var: Переменные, объявленные с помощью var, имеют функциональную область действия, что означает, что к ним можно получить доступ только в рамках функции, в которой они были объявлены. Внешняя переменная затеняется, когда переменная с тем же именем объявляется во вложенной функции.
  • let: Пусть переменные имеют блочную область действия, что означает, что они доступны только в том блоке, в котором они объявлены. Объявление переменной с тем же именем во вложенном блоке приведет к затенению внешней переменной.
  • const: переменные, объявленные с помощью const, также как let, имеют область действия блока, но их нельзя переназначить.
Вот пример:
function example() {
  var x = 1;
  let y = 2;
  const z = 3;

  if (true) {
    var x = 4;
    let y = 5;
    const z = 6;
  }

  console.log(x); // 4
  console.log(y); // 2
  console.log(z); // 3
}

example();

6. Какова разница между == и ===?

Оператор равенства == выполняет принудительное приведение типа, что означает, что он попытается преобразовать операнды в один и тот же тип перед их сравнением. С другой стороны, оператор строгого равенства ===, не выполняет приведение типа. Он возвращает значение true только в том случае, если оба операнда имеют одинаковый тип и значение. Например:
console.log(1 == '1'); // true
console.log(1 === '1'); // false

7. В чем разница между null и undefined?

undefined указывает, что переменная была объявлена, но ей не было присвоено значение. Значение nullпредставляет собой преднамеренное отсутствие какого-либо значения объекта. Другими словами, null — это явно заданное значение, указывающее на отсутствие значения.

8. Что такое событие в JavaScript?

В JavaScript событие — это любое действие в браузере, например нажатие пользователем кнопки, загрузка страницы или обновленный элемент. Слушатели событий обычно обрабатывают события, позволяя разработчикам указывать функции, которые должны выполняться при возникновении события. Пример:
const button = document.querySelector('button');

button.addEventListener('click', () => {
  console.log('Button was clicked!');
});

9. В чем разница между синхронным и асинхронным кодом в JavaScript?

Синхронный код выполняется блокирующим образом, что означает, что следующая строка кода будет выполнена после завершения текущей строки. С другой стороны, асинхронный код выполняется неблокирующим образом, что означает, что другой код может выполняться не ожидая завершения асинхронного кодом. Асинхронный код обычно реализуется в JavaScript с помощью обратных вызовов или Promises.

10. Что такое промисы (Promise) в JavaScript?

Объект Promise — это объект, представляющий успешное или неудачное завершение асинхронной операции. Promise позволяет регистрировать обратные вызовы для получения уведомлений о завершении или сбое асинхронной операции, а также обрабатывать ошибки более удобно и централизованно. Например:
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched!');
    }, 1000);
  });
};

fetchData()
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

11. Что такое обратный вызов в JavaScript?

Функция обратного вызова передается в качестве аргумента другой функции и выполняется после завершения внешней функции. Разработчики могут использовать обратные вызовы для указания кода, который будет выполняться после завершения асинхронной операции. Пример:
const fetchData = (callback) => {
  setTimeout(() => {
    callback('Data fetched!');
  }, 1000);
};

fetchData(data => {
  console.log(data);
});

12. Что такое AJAX в JavaScript?

AJAX (асинхронный JavaScript и XML) — это метод выполнения асинхронных серверных запросов с веб-страницы без перезагрузки всей страницы. AJAX позволяет разработчикам динамически обновлять веб-страницу новыми данными без необходимости обновления страницы. Это достигается путем отправки HTTP-запроса из браузера на сервер и обновления только тех частей страницы, которые требуют его с ответом. Это улучшает взаимодействие с пользователем, поскольку страница не перезагружается, а обновляются только необходимые данные. Пример:
const xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.example.com/data');

xhr.onreadystatechange = () => {
  if (xhr.readyState === XMLHttpRequest.DONE) {
    console.log(xhr.responseText);
  }
};

xhr.send();
Еще больше вопросов с собеседований можно найти здесь.