Создавая приложение для ведения заметок при помощи Next.js вы бы следовали такой схеме:
- Построение системы авторизации с помощью NextAuth .
- Ее привязывание к MongoDB для сохранения пользователей в базе данных.
- Если вам требуется синхронизация в реальном времени, то написание системы, которая будет реагировать на события в БД соответствующими действиями.
Может показаться, что сделать это легко, но программирование слушателя событий является не столь простой задачей.
Здесь нам на помощь приходит Supabase . Это общедоступный конкурент Firebase, который предоставляет множество сервисов для улучшения приложения. Если при создании блокнота для заметок вы предпочтете задействовать Supabase, то выполнить нужно будет такие шаги:
- Использовать сервис Auth , предоставляющий множество провайдеров авторизации в нескольких строках кода.
- Применить механизм Realtime , который за вас будет обрабатывать все процессы реального времени. Останется лишь сообщить фронтенду о необходимости отображения любых изменений при возникновении события.
В текущей статье мы создадим в Supabase приложение-блокнот с аутентификацией:
Практика JavaScript с нуля за 2 часа. Сделаем целый сайт!
Что мы получим в итоге
В этом приложении также будет использоваться Realtime API, которое позволит Next.js отрисовывать новые заметки без обновления страницы:
Демонстрация работы в реальном времени
Подготовка
Прежде чем перейти к сути, нам понадобиться создать активный проект Supabase.
Создание проекта Supabase
Для этого переходим на страницу Supabase Project и кликаем “New Project”. Здесь регистрируем учетные данные.
Регистрация учетных данных
После переходим в “Settings” и кликаем “API”:
Панель Api
Находясь в этой панели, скопируйте ваши ключи URL и anon public:
Извлечение ключей
Затем перейдите в проект Next.js и вставьте их в .env.local:
NEXT_PUBLIC_SUPABASE_URL = SupabaseURL
NEXT_PUBLIC_SUPABASE_ANON_KEY = AnonPublicKey
Теперь переходим к настройке экрана Google OAuth.
Google OAuth
Зайдите в Google Cloud Console и создайте новый Oauth Client ID. В разделе “Authorized redirect URIs” введите URL вашего проекта Supabase + /auth/v1/callback.
Страница “Authorized redirect URIs”
В завершении нужно ввести в Supabase ваши учетные данные Google. Для этого вернитесь к панели Supabase и вставьте ключи в раздел “Google Enabled” на странице “Auth Settings”.
Вставка ключей Google
А теперь напишем для нашего проекта код системы авторизации.
Аутентификация Google
Примечание: в этой статье мы реализуем только клиентскую аутентификацию. Если же вы захотите узнать об аутентификации в Supabase более подробнее, то почитайте эту статью (англ.).
Установка модулей и настройка проекта
Потребуются следующие пакеты:
Для установки перечисленных зависимостей выполните в терминале:
В качестве второго шага удалите в файле pages/index.js код между тегами div, чтобы в итоге index.js выглядел так:
Как начать делать приложения на JavaScript
export default function Home() return ;
>
Структура файлов проекта
Создайте следующие каталоги в директории проекта Next.js:
- utils: здесь будут находиться служебные функции, а также конфигурация клиента Supabase.
- components: здесь будут находиться настраиваемые компоненты.
В итоге у проекта должна получиться такая структура:
Файловая структура проекта
Отлично! В следующем разделе мы настроим клиента Supabase.
Настройка Supabase
В каталоге utils создайте файл supabaseClient.js и пропишите в нем следующий код:
- Строки 3–4: получаем ключи клиента из .env.local.
- Строка 5: передаем эти значения в функцию createClient. Так мы инициализируем экземпляр Supabase.
- Строка 7: экспортируем эту конфигурацию Supabase, чтобы использовать ее в проекте.
Далее мы напишем код, который позволит пользователю авторизовываться в приложении и выходить из него.
Служебные функциии авторизации
В каталоге utils создайте файл authentication.js. В нем наберите:
- Строка 2: вызываем функцию auth.signIn. Она будет авторизовывать пользователя с помощью его Google-аккаунта.
- Строка 7: позволяет выходить из аккаунта.
Вот и все! Теперь настроим компонент аутентификации.
Компонент аутентификации
В каталоге components создайте файл Container.js. В этом файле запишите следующий код:
- Строка 7: хук Auth.useUser будет извлекать пользовательские данные.
- Строка 10: если пользователь авторизовался, отображает его имя.
- Строка 13: при клике вызывает метод signOut.
- Строка 14: позволяет пользователю проследовать по маршруту /note. Этот маршрут мы обработаем позже.
- Строка 17: если пользователь не авторизован, отображает дочерние элементы этого компонента.
В качестве второго шага перейдите в pages/_app.js и измените его код так:
- Строки 6–8: компонент Auth использует React’s Context API для отправки пользовательских данных, а также данных текущей сессии. Это позволит сохранять пользовательские сессии между разными маршрутами.
Отлично! Теперь займемся интерфейсом авторизации.
Создание UI авторизации
В /pages/index.js производим следующий импорт:
Далее находим блок return:
Изменяем его так:
- Строка 3: передает экземпляр Supabase в Container в качестве пропса.
- Строка 4: при клике вызывает метод signIn.
Выполняем код и получаем следующий результат:
Результат кода
Отлично! Код работает. Далее займемся построением вокруг него самого приложения.
В итоге /pages/index.js должен выглядеть так:
Функциональность внесения заметок
Прежде, чем писать код, нужно настроить базу данных.
Настройка базы данных
Перейдите в проект Supabase и кликните по вкладке “SQL”, чтобы открыть редактор SQL:
Переход в SQL-редактор
Здесь пишем следующий код SQL:
- Строка 3: в таблице notes у нас будет поле user_id, связывающее ее с auth.users, что позволит создать реляционную таблицу.
- Строки 4–5: у нее также будут поля heading и body с типом text.
- Строка 8: активируем row-level security , необходимую для создания политик.
- Строки 10–17: создаем политики Supabase . Если кратко, то здесь мы сообщаем Supabase, что пользователь имеет доступ к выполнению операций в БД со своими записями.
После этого нужно настроить таблицу на использование Realtime API. Для этого выполняем следующие шаги:
Активация Realtime для таблицы
Это означает, что при каждом выборе пользователем записи Supabase будет уведомлять об этом приложение. Таким образом, приложение сможет показывать изменения без обновления веб-страницы.
Еще один этап завершен! Теперь перейдем к написанию кода вспомогательных функций, которые будут выполнять для базы данных операции CRUD.
Служебные функции
В каталоге utils создайте файл note.jsи введите в нем следующий код:
- Строки 4–7: получаем пользовательские записи из таблицы notes и упорядочивает их по возрастанию id.
- Строки 13–16: вставляем заметку в таблицу.
- Строки 24–27: находим заметку с нужным id и удаляем.
После этого можно заняться интерфейсом, который позволит пользователям создавать заметки.
Компонент AddForm
Перейдите в каталог /components/ и создайте файл AddForm.js. В нем введите следующее:
- Строки 8–9: значения-плейсхолдеры для текстовых полей body и heading будут пустыми.
- Строки11–13: при отправке пользователем формы вызываем метод add, который вставляет запись в базу данных.
- Строки 16–17: создаем поля heading и body.
Закончив с AddForm, пора переходить к созданию GUI, который даст пользователю возможность удалять заметки.
Страница Notes и активация подписок
В каталоге /pages создайте файл note.js. В нем введите следующий код:
- Строки 8–10: создаем хуки для хранения пользовательских заметок, чтобы иметь возможность отображать их в DOM.
- Строки 14–18: получаем данные из БД и сохраняем результаты в хуке data. Подписываемся на изменения, происходящие в таблице notes БД в реальном времени.
- Строки 21–30: Подписываемся на изменения, происходящие в таблице notes БД в реальном времени. Если пользователь создал запись (событие INSERT), то сохраняем ее в хуке newData. Кроме того, если пользователь удаляет запись (событие DELETE), тогда устанавливаем значение deleteData на эту удаленную заметку.
Теперь нужно прописать логику, которая будет обрабатывать создание/удаление записей. Для этого добавляем в pages/note.js следующий код:
- Строки 2–3: при первом монтировании компонента запускаем функцию getData и метод подписки.
- Строка 6: отписываемся от Realtime, чтобы избежать утечек памяти.
- Строки 12–14: если newData не null, добавляем значение newDataв массив data.
- Строка 19: если у deletedData есть значение, удаляем связанный элемент из массива data.
Теперь нам остается лишь отрисовать интерфейс. Для этого пишем в /pages/note.js следующий код:
- Строка 3: отрисовываем элемент AddForm и передаем его в пользовательские данные в качестве пропса.
- Строки 5–10: вызываем метод map для массива data и отображаем поля heading, body и id каждого элемента.
- Строка 11: при клике удаляем указанную заметку.
Выполните код и перейдите в каталог /note. Результат должен выглядеть так:
Вывод кода
Вот мы и закончили! Чтобы пронаблюдать real-time функциональность, откройте два экземпляра приложения:
Realtime работает!
Заметьте, что нам не пришлось обновлять приложение для просмотра изменений. Это подтверждает, что режим реального времени в Supabase работает, как положено.
В итоге /pages/note.js должен выглядеть так:
export default function Note() const [data, setData] = useState([]);
const [newData, handleNewData] = useState(null);
const [deletedData, handleDeletedData] = useState(null);
const getData = async () => const data = await fetchData();
setData(data);
console.log(data);
>;
const getChange = async () => const mySubscription = supabaseClient
.from(«notes»)
.on(«INSERT», (payload) => handleNewData(payload.new);
>)
.on(«DELETE», (payload) => console.log(payload.old.id);
handleDeletedData(payload.old);
>)
.subscribe();
return mySubscription;
>;
useEffect(() => getData();
const mySubscription = getChange();
useEffect(() => console.log(«newData value», newData);
if (newData) setData([. data, newData]);
handleNewData(null);
>
>, [newData]);
useEffect(() => if (deletedData) setData(data.filter((data) => data.id !== deletedData.id));
>
// eslint-disable-next-line react-hooks/exhaustive-deps
>, [deletedData]);
return (
/>
Here’s your data:
(
,
deleteNote(item.id)>> Remove
))>
);
>
Supabase — это удобная в использовании библиотека, включающая разнообразные возможности, которые упрощают процесс разработки. А благодаря открытому доступу она становится отличным выбором для программистов, которые предпочитают использовать в приложениях open source-технологии. Если у вас есть проект, которому нужна аутентификация и прочие возможности, Supabase станет отличным дополнением для набора инструментов.
- Топ-9 PET-проектов для начинающих javascript-разработчиков
- 3 совета, как стать мастером Йода по JavaScript
- Как использовать JavaScript и Node.js, чтобы сразиться с драконом в игре Fight the Dragon?
Источник: dzen.ru
Node JS и React — как создать фулстек приложение. Полное руководство
React приложение и бэкенд на NodeJS это хорошее сочетание, которое подойдет для реализации практически любых сервисов. Эта статья поможет вам быстро создать фулстек приложение.
Необходимые инструменты
- NodeJS и npm. Их можно скачать с официального сайта nodejs.org. npm установится автоматически вместе с NodeJS.
- Предпочитаемый IDE, например, Visual Studio Code.
- Опционально, установить git для удобной работы с кодом.
О приложении
В этой статье напишем приложение, которое будет получать и отображать список дел. Структура папок будет выглядеть следующим образом.
app/ frontend/ backend/
Создание бэкэнда на NodeJS
Запустим команду в папке app/backend для инициализации проекта:
npm init -y
Эта команда создаст файл package.json . Этот файл содержит как общую информацию о проекте (название, версия, описание и т.д.), так и информацию о зависимостях, скрипты для запуска, сборки и тестирования. Для создания сервера будем использовать express. Установим его с помощью команды:
npm i express
Создадим файл index.js , который будет содержать код для запуска сервера. Этот код запускает веб сервер на порту 3010 , если он не задан в переменных среды.
// backend/index.js const express = require(‘express’); const PORT = process.env.PORT || 3010; const app = express(); app.use((req, res, next) => < res.setHeader(‘Access-Control-Allow-Origin’, ‘*’); next(); >); app.listen(PORT, () => < console.log(`Server listening on $`); >);
Добавим команду для запуска сервера в package.json . В результате сможем запускать наш сервер с помощью команды npm start .
// backend/package.json . «scripts»: < «start»: «node ./index.js» >, .
Из директории app/backend запустим команду npm start . Если ошибок нет, получим сообщение, что сервер прослушивает порт 3010.
Создание API
API это интерфейс, с помощью которого React приложение будет общаться с веб-сервером, т.е. запрашивать, изменять или удалять данные. В нашем случае мы создадим API для получения списка дел в формате JSON. Создадим файл todo-items.json c объектами todo. Этот массив будем отдавать по запросу /api/todo-items .
Следующий код создает эндпоинт /api/todo-items . React приложение будет отправлять GET запрос на этот эндпоинт.
// backend/index.js // . const todoItems = require(‘./todo-items.json’); app.get(‘/api/todo-items’, (req, res) => < res.json(< data: todoItems >); >); app.listen(PORT, () => < console.log(`Server listening on $`); >);
Для того чтобы изменения вступили в силу, нужно перезапустить NodeJS сервер. Для остановки скрипта — в терминале, в котором запущен npm start , нужно нажать Ctrl + C ( Command + C ). Далее снова запускаем npm start . Для проверки эндпоинта, в браузере перейдем по адресу http://localhost:3010/api/todo-items . В результате получим, такой ответ.
Создание фронтенда на React
В папке app/ откроем новый терминал и запустим команду для создания React приложения, где frontend имя нашего приложения.
Дождемся установки всех зависимостей. В терминале перейдем в папку frontend .
cd ./frontend
Установим библиотеку bootstrap для дальнейшего использования готовых компонентов.
npm install react-bootstrap bootstrap
Заимпортируем bootstrap.min.css в файле frontend/src/index.js .
import ‘bootstrap/dist/css/bootstrap.min.css’;
Запустим приложение командой npm start .
npm start
Получим следующее сообщение. Перейдем по указанному адресу в браузере.
Compiled successfully! You can now view frontend in the browser. Local: http://localhost:3003 On Your Network: http://192.168.99.1:3003 Note that the development build is not optimized. To create a production build, use npm run build.
Отправка HTTP запроса из React в NodeJS
К этому моменту у нас уже есть рабочий сервер, который умеет принимать запросы и отдавать данные. Сделаем запрос на /api/todo-items из React приложения. Для этого вызовем функцию fetch из хука useEffect в файле App.js .
// frontend/src/App.js import < useState, useEffect >from ‘react’; import Form from ‘react-bootstrap/Form’; import ‘./App.css’; function App() < const [todoItems, setTodoItems] = useState([]); useEffect(() => < fetch(‘http://localhost:3010/api/todo-items’) .then((res) =>res.json()) .then((result) => setTodoItems(result.data)); >, []); return ( ( className=»app__todo-item»> /> /> ))> ); > export default App;
Открыв приложение в браузере, получим такой результат. Исходный код
5 кастомных React хуков, которые улучшат ваш код
4 месяца назад · 3 мин. на чтение
В этой статье рассмотрим несколько очень полезных React хуков.
1. Хук useWindowSize — хук для получения размера экрана
Я уверен, что в некоторых проектах, над которыми вы работали, вам нужно было получить ширину и высоту окна пользователя. Так вот, теперь у вас есть хук для этого, так что вы можете сделать это еще проще, чем раньше.
import < useState, useEffect >from «react»; interface WindowSize < width: number; height: number; >const useWindowSize = (): WindowSize => < const [windowSize, setWindowSize] = useState(< width: window.innerWidth, height: window.innerHeight, >); useEffect(() => < const handleResize = () =>< setWindowSize(< width: window.innerWidth, height: window.innerHeight, >); >; window.addEventListener(«resize», handleResize); return () => < window.removeEventListener(«resize», handleResize); >; >, []); return windowSize; >;
Этот хук может быть особенно полезен при реализации отзывчивого дизайна, когда по какой-то причине вам нужно запустить определенный код при определенных размерах. Более продвинутый вариант этого хука можно найти в статье “Хук useResize для отслеживания ширины экрана в ReactJS”.
2️. Хук useKeyPress — хук для определения нажатия клавиши
Следующий хук позволяет определить, когда нажата определенная клавиша. Это может вызвать события или действия, основанные на нажатой клавише. Например, для закрытия модального окна, отправки формы и т.д.
import < useState, useEffect >from «react»; const useKeyPress = (targetKey: string): boolean => < const [keyPressed, setKeyPressed] = useState(false); const downHandler = (< key >: KeyboardEvent) => < if (key === targetKey) < setKeyPressed(true); >>; const upHandler = (< key >: KeyboardEvent) => < if (key === targetKey) < setKeyPressed(false); >>; useEffect(() => < window.addEventListener(«keydown», downHandler); window.addEventListener(«keyup», upHandler); return () =>< window.removeEventListener(«keydown», downHandler); window.removeEventListener(«keyup», upHandler); >; >, []); return keyPressed; >;
const closeModalKeyPress = useKeyPress(«Escape»);
3. Хук useInterval — хук для вызова функции setInterval
Этот хук позволяет вам использовать функцию setInterval в качестве хука. Как и функция setInterval , этот хук имеет множество применений, например, анимация, обновление данных через регулярные промежутки времени или даже установка таймера.
import < useState, useEffect, useRef >from «react»; const useInterval = (callback: () => void, delay: number | null) => < const savedCallback = useRefvoid>(); useEffect(() => < savedCallback.current = callback; >, [callback]); useEffect(() => < function tick() < savedCallback.current savedCallback.current(); >if (delay !== null delay > 0) < let delay); return () =>clearInterval(id); > else < tick(); >>, [delay]); >;
Можно использовать этот хук следующим образом:
const [count, setCount] = useState(0); useInterval(() => < setCount(count + 1); >, 1000);
4. Хук useDebounce
Теперь мы поговорим о хуке, который выполняет функцию только после того, как пройдет определенное количество времени без ее вызова. Это полезно, например, для ограничения скорости вызовов API или обновления состояния при изменении ввода, например, когда вы набираете текст в поисковой строке.
import < useEffect, useRef >from ‘react’; export function useDebounce(callback:Function, timeout: number = 200, deps: Array = []) < const data = useRef(< firstTime: true >); useEffect(() => < const < firstTime, clearFunc >= data.current; const handler = setTimeout(() => < if (clearFunc typeof clearFunc === ‘function’) < clearFunc(); >data.current.clearFunc = callback(); >, timeout); return () => < clearTimeout(handler); >; >, [timeout, . deps]); > export default useDebounce;
const [inputValue, setInputValue] = useState(«»); useDebounce(() => < // вызов APIl >, 500);
5️. Хук useThrottle
Throttle означает, что функция будет выполняться один раз за каждый заданный промежуток времени. Это может быть полезно для предотвращения быстрого запуска слишком большого количества вызовов API или событий.
import < useEffect, useRef >from ‘react’; export const useThrottle = (callback:Function, delay: number = 200, deps: Array = []) => < const lastRan = useRef(Date.now()); useEffect( () =>< const handler = setTimeout(function() < if (Date.now() — lastRan.current >= delay) < callback(); lastRan.current = Date.now(); >>, delay — (Date.now() — lastRan.current)); return () => < clearTimeout(handler); >; >, [delay, . deps], ); >; export default useThrottle;
const [inputValue, setInputValue] = useState(«»); useThrottle(() => < // вызов API >, 500);
Еще больше крутых хуков вы можете найти в каталоге хуков.
Источник: it-dev-journal.ru
Пишем полноценное приложение на React с нуля за час
В этой статье вы познакомитесь с React — библиотекой для создания пользовательских интерфейсов. React появился в 2013 году и достаточно быстро стал популярным среди разработчиков. Сегодня в работе над веб-приложениями его используют Facebook, Instagram, Trello, AirBnb, PayPal. С помощью этой статьи мы сможем написать приложение прогноза погоды: от установки с помощью create-react-app (проект на GitHub) до подключения API и стилей bootswatch.
Прим. перев. Если вы начинаете изучение React, вам также стоит прочитать наш материал, в котором разработчик делится советами по использованию этой библиотеки.
Этот материал был написан для воркшопа Open Source Dev Garage, прошедшего в рамках конференции разработчиков F8 2017. Чтобы лучше разобраться в том, как написать это приложение, посмотрите 48-минутное видео или следуйте письменным инструкциям в этом руководстве.
Просмотрев семинар или изучив руководство, вы создадите простое приложение прогноза погоды:
Создайте ваше первое приложение
Прежде всего вам понадобится node.js и редактор кода, например, Atom.
Откроем терминал и установим create-react-app :
npm install -g create-react-app
Примечание: Пользователям Linux или MacOS, возможно, потребуется дополнительно ввести команду sudo перед npm install -g .
Начнем создавать наше приложение прогноза погоды:
create-react-app weather
Данной командой мы установим набор инструментов, которые помогут создать наше React-приложение. По завершении установки мы сможем запустить приложение командами:
cd weather npm start
Новое приложение автоматически откроется в браузере!
Свойства и компоненты
Давайте взглянем на приложение, которое create-react-app создал автоматически. В редакторе кода откроем weather/src/App.js :
class App extends Component < render() < return ( className=»App-logo» alt=»logo» />
Welcome to React
To get started, edit src/App.js and save to reload.
); > >
Наше приложение состоит из одного компонента, где функция render() является его главной составляющей. Напишите какой-нибудь текст, сохраните изменения и посмотрите, как приложение автоматически применит их!
Тестировщик АО «Гринатом» , , можно удалённо , По итогам собеседования
Теперь создадим новый компонент WeatherDisplay . Так как функция render() — это «сердце» компонента, то именно она определяет, что будет отображено. Для начала создадим тег с каким-нибудь текстом внутри:
class WeatherDisplay extends Component < render() < return (
Displaying some Weather!
); > >
Изменим компонент App , чтобы отобразить наш WeatherDisplay :
class App extends Component < render() < return ( /> ); > >
Как видите, мы передали данные, которые обозначили переменной zip , в компонент WeatherDisplay . Они называются свойствами (props). Мы можем модифицировать наш компонент для отображения передаваемых данных:
class WeatherDisplay extends Component < render() < return ( Displaying weather for city ); > >
Где-нибудь в начале файла добавим несколько городов, для которых мы хотели бы отобразить погоду:
const PLACES = [ < name: «Palo Alto», zip: «94303» >, < name: «San Jose», zip: «94088» >, < name: «Santa Cruz», zip: «95062» >, < name: «Honolulu», zip: «96803» >];
Обновим render() в компоненте App , в котором, перебирая массив PLACES , создадим тег button для каждого города:
return ( /> ( onClick= < console.log(‘Clicked index ‘+index); >> > ))> );
Из массива данных мы создадим набор элементов button и назначим свойство key для каждого, чтобы React знал последовательность элементов в массиве.
Здесь также есть обработчик событий onClick , который при нажатии будет выводить сообщение в консоль браузера. Открыв панель разработчика в браузере, вы можете увидеть логи событий. Ваше приложение должно выглядеть так:
На этом этапе файл App.js должен выглядеть так.