Эта статья будет лучшим местом для начала, если вы новичок в Redis или хранилище данных Redis-JSON. Хотя вы должны быть знакомы с некоторым javascript и реагировать на js.

В этом уроке мы будем создавать todo-приложение в базе данных Redis и next js с нуля. Ничего страшного, если вы не знакомы с базой данных Redis. Мы начнем с нуля. Окончательное приложение сможет выполнять операции CRUD с использованием redisJSON и Next JS, которые мы будем использовать в качестве интерфейсной среды.

Как новичок, когда я начал работать с операциями CRUD, я помню, что изо всех сил пытался найти правильные команды для реализации операций CRUD в приложении, использующем базу данных. Именно поэтому я запланировал написать полное руководство по работе с грубыми операциями базы данных Redis с использованием redisJSON, а также буду использовать исследования для поиска наших добавленных задач.

Посмотрите это видео о том, почему стоит выбрать Redis в качестве базы данных:

Живое приложение и исходный код

Это предварительный просмотр того, что мы будем строить в конце.

Живое приложение

"Исходный код"

Предварительные требования:

В вашей системе должны быть установлены следующие вещи:

  • NodeJS: последняя LTS-версия. Я использовал версию v16.15.1
  • Редактор кода: используется VS Code, но вы можете выбрать редактор по своему усмотрению.
  • Я предполагаю, что вы знакомы с javascript, Next JS (или React JS) и имеете опыт программирования не менее шести месяцев.

Что такое Редис?

Ну, это не база данных SQL. А точнее Redis — это хранилище ключей и значений в памяти, которое часто используется в качестве кеша для ускорения работы традиционных баз данных. Тем не менее, она превратилась в мультимодельную базу данных, поддерживающую полнотекстовый поиск, взаимосвязи графов, рабочие нагрузки ИИ и многое другое.

Что такое RedisJSON?

RedisJSON — это модуль Redis, обеспечивающий поддержку JSON в Redis. RedisJSON позволяет хранить, обновлять и извлекать значения JSON в Redis так же, как и с любым другим типом данных Redis. RedisJSON также без проблем работает с RediSearch, позволяя вам индексировать и запрашивать ваши документы JSON. Это лучший способ работы с базой данных Redis.

Начальная настройка

Примечание. Я мог бы просто попросить вас перейти по ссылке, чтобы зарегистрироваться в Redis и настроить базу данных самостоятельно, и, возможно, новички с трудом справляются с этим, поэтому я не хочу, чтобы кто-то из вас боролся в выполнении каждого шага, как я боролся в начале, и я собираюсь направлять вас шаг за шагом и в деталях, чтобы ни у кого из вас не было путаницы после меня. Если вы думаете, что можете сделать это легко самостоятельно. Просто пропустите этот раздел.

Итак, давайте начнем.

1) Зарегистрируйтесь в облаке Redis

Самый быстрый способ начать использовать базу данных Redis — использовать их бесплатный уровень в Redis Enterprise Cloud.

Вы увидите эту страницу.

Вы можете зарегистрироваться с помощью Github или Google, либо введя информацию формы.

2) Активируйте подписку уровня бесплатного пользования

  • После успешной регистрации вы будете перенаправлены на эту страницу.

  • Теперь вам нужно активировать бесплатный план подписки. Чтобы сделать это. Вы должны нажать на кнопку «Активировать подписку», как показано ниже.

Затем вы будете перенаправлены на эту страницу:

  • Вы можете выбрать бесплатный план. Или гибкий или годовой план в зависимости от вашего варианта использования.
  • Затем выберите AWS, Google или Mircosoft Azure, который вам больше нравится. Это полностью ваш выбор, как показано ниже.

  • Затем, когда вы будете прокручивать вниз. Вы можете выбрать необходимое хранилище данных. 30 МБ будут доступны бесплатно. Вы можете использовать код купона TIGER200!🔥.

ПРИМЕЧАНИЕ. В течение ограниченного времени. Вы получите 200 долларов кредитов, используя код купона TIGER200!🔥. Так что зарегистрируйтесь сегодня на Redis Enterprise, чтобы начать.

  • Вы можете дать подписке любое имя. Например, бесплатная подписка показана на изображении ниже.

  • Теперь нажмите «Создать подписку», чтобы активировать подписку, как показано ниже.

  • Как только вы нажмете кнопку «Создать подписку», ваша подписка будет активирована, и она будет отображаться на вкладке подписки, как показано на изображении ниже.

3) Создайте новую базу данных.

До сих пор мы активировали нашу подписку. Теперь пришло время создать новые данные.

  • Чтобы создать новую базу данных, нажмите эту кнопку, оставаясь на предыдущей странице, как показано на изображении ниже.

  • Теперь вы будете перенаправлены на создание мастера базы данных. Здесь дайте вашей базе данных имя, например MyFirstRedisDatabase, и в типе выберите Redis и выберите модули RedisJSON и RediSearch, так как мы собираемся использовать оба в нашем приложении. Это показано ниже:

  • При прокрутке вниз до следующего шага оставьте все по умолчанию, как показано ниже:

  • Теперь, чтобы активировать базу данных, нажмите «Активировать базу данных» в правом верхнем углу, как показано ниже:

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

  • Кроме того, вы можете увидеть свою базу данных, нажав вкладку «Базы данных» в верхнем левом углу, как показано ниже.

  • Вы увидите, что ваша база данных активирована и указана в разделе баз данных, как показано ниже:

4) Добавление ролей в нашу базу данных.

  • Для этого перейдите на вкладку «Контроль доступа к данным», нажав третью опцию на боковой панели, как показано ниже.

  • Вас направят сюда:

  • Теперь нажмите на вкладку «Роли», как показано ниже.

  • Вы увидите этот вид.

  • Теперь нажмите кнопку «Добавить новую роль», как показано ниже.

  • Вы увидите этот вид.

  • Теперь назовите роль администратором и выберите подписку в раскрывающемся списке базы данных, как показано ниже.

  • Затем выберите «Полный доступ» в раскрывающемся списке Redis acls, как показано ниже.

  • Затем нажмите кнопку с галочкой, как показано ниже.

  • Затем нажмите кнопку «Сохранить роль» в правом нижнем углу, как показано ниже.

Роль будет сохранена с именем «Администратор» с выбранными нами характеристиками, и вы увидите следующий предварительный просмотр.

5) Добавление пользователей в Контроль доступа к данным.

Теперь последний шаг — добавить пользователей, чтобы пользователи, которых вы добавите, имели доступ к базе данных и могли читать, писать и выполнять операции с базой данных в зависимости от их доступа. Теперь мы просто дадим все разрешения пользователю, которого мы будем добавлять. Давайте начнем.

  • Теперь нажмите вкладку «Пользователи», как показано ниже.

  • Нажмите кнопку «Новый пользователь», как показано ниже.

  • Теперь введите имя пользователя, например: bilal, и выберите роль администратора, а затем введите пароль, например: Pass1233456789!. Вы можете написать свое имя пользователя и пароль, а затем нажать «ОК», как показано ниже.

Примечание. Обратите внимание, что имя пользователя и пароль, которые вы указываете, необходимо запомнить и сохранить в безопасном месте, поскольку мы будем использовать это имя пользователя и пароль для доступа к базе данных Redis из базы кода нашего внутреннего сервера Node JS. .

  • Через некоторое время статус станет зеленым, что означает, что пользователь успешно добавлен.

Поздравляем с завершением. Теперь давайте начнем создавать нашу интерфейсную часть.

Разработка внешнего интерфейса приложения Todo.

Внешний вид приложения todo будет таким, как показано на изображении ниже.

1) Создание нового следующего приложения js.

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

  • Чтобы создать следующее js-приложение, перейдите в пустую папку. В этой папке откройте cmd. Так же, как показано ниже для окон.

  • Теперь удалите путь и напишите здесь cmd и нажмите ввод. Откроется терминал в каталоге, в котором вы находитесь. Как показано ниже.

  • Терминал будет открываться так для пользователей Windows, как я работаю в Windows, в то время как пользователи Linux хорошо учатся, они знают, как открыть терминал.

  • Теперь в командной строке введите следующую команду.
npx create-next-app todoappnextjsredis

Нажмите Enter после того, как вы напишете команду в командной строке

  • Это будет отображаться в командной строке следующим образом. Шаблон для создания следующего приложения будет запущен для загрузки.

  • Теперь сядьте поудобнее и подождите 🙂, пока модули узла не будут установлены и не будет загружен шаблон для создания следующего приложения.
  • После установки в терминал напишите следующую команду, чтобы перейти в следующий каталог приложения js и запустить следующий сервер js.
cd todoappnextjsredis && npm run dev
  • Он будет отображаться в терминале следующим образом.

  • Следующий js сервер будет запущен на localhost:3000

2) Пишем наш интерфейсный код для приложения todo.

  • Откройте VS Code в корне папки todoappnextjsredis.
  • Вы можете ввести эту команду в командной строке в корне каталога todoappnextjsredis.
code .

  • Код Visual Studio в этом каталоге будет открыт. Теперь пришло время начать писать интерфейсный код.

Добавление библиотеки Mdbootstrap для стилей

Mdbootstrap – это набор пользовательского интерфейса, созданный с целью сократить время, необходимое разработчикам для создания своих веб-сайтов, за счет использования всех лучших функций ванильного Bootstrap и улучшения их отличительным дизайном от Google.

  • Перейдите к этому файлу pages\_app.js.

Удалите весь код и вставьте следующий.

//pages\_app.js
import Head from 'next/head';
import Script from 'next/script';
import '../styles/globals.css'

function MyApp({ Component, pageProps }) {

 return <>

  <Head>
   <meta charSet="utf-8" />
   <meta name="description" content="A todo app built with Next JS,redis,Node JS and Express" />
   <meta name="keywords" content="TodoApp,NextJS,Redis,NodeJS,Express,Realtime" />
   <meta name="author" content="Muhammad-Bilal-7896" />
   <meta name="viewport" content="width=device-width, initial-scale=1" />
   <meta name="theme-color" content="#000000" />
   <title>NextJSRedisTodoApp</title>
  </Head>

  <Component {...pageProps} />

  <Script
   type="text/javascript"
   src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.5.0/mdb.min.js"
  ></Script>
 </>
}

export default MyApp;

Как и в последних версиях next js, теги script устарели, и вместо них предпочтительны теги script Script из next js.

  • Теперь перейдите в папку с этой страницей и создайте новый файл с именем document.js и вставьте следующий код после удаления предыдущего. Это будут страницы/_document.js
// pages/_document.js

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {

  return (

    <Html>

      <Head>

        {/* Font Awesome */}

        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet" />

        {/* Google Fonts */}

        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />

        {/* MDB */}

        <link href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.5.0/mdb.min.css" rel="stylesheet" />

        {/* <!-- MDB --> */}

      </Head>

      <body>

        <Main />

        <NextScript />

      </body>

    </Html>

  )

}

Теперь Mdbootstrap успешно добавлен в наш проект.

Написание интерфейсной части.

  • Перейдите к файлу в этом месте pages\index.js. Переименуйте файл index.js в index.jsx, так как это позволит улучшить IntelliSense. Удалите весь код по умолчанию и вставьте следующий код.
//pages\index.js

import { useEffect, useState } from "react";

import Head from 'next/head';

import Image from 'next/image';

//Importing Compoents

import Header from '../Components/Header';

import Footer from '../Components/Footer';

import TodoList from '../Components/Home/TodoList';


function Home() {

 const [addTodoValue, setAddTodoValue] = useState('');

 const [todoList, setTodoList] = useState([]);

 const [isCompleted, setIsCompleted] = useState(false);


 useEffect(() => {

  (async () => {

   const response = await fetch('http://localhost:8000/todo');

   const content = await response.json();

   setTodoList(content);

  })();

 }, []);


 useEffect(() => {

  console.log(`The TodoList is equal to : ${todoList}`);

 })


 const handleAddTodo = async (e) => {

  if (addTodoValue.length > 0) {

   e.preventDefault();

   const response = await fetch('http://localhost:8000/todo', {

    method: "POST",

    headers: { 'Content-Type': 'application/json' },

    body: JSON.stringify({

     title: addTodoValue,

     timeSubmitted: new Date().toLocaleString(),

     completed: isCompleted

    })

   });


   const todo = await response.json();

   setTodoList([...todoList, todo]);

   alert(`The value will be added to TodoList: ${addTodoValue}`);

  } else {

   alert('Please enter a value to add to TodoList');

  }

 }


 return (

  <div>

   <Head>

    <title>TodoAppNextJSRedis</title>

   </Head>

   <Header />

   <div className={`container`}>

    <div className={`row`}>

     <div className={`col-12`}>

      <br />

      <h1 className='text-center text-info'>NextJS & Redis Based Todo App</h1>

      <form className='form_styling' onSubmit={handleAddTodo}>

       <div className='d-flex'>

        <div className='addItemInput'>

         <input className='form-control w-80' placeholder='Please Type Any Value to Add to the Todo' onChange={(e) => setAddTodoValue(e.target.value)} type="text" />

        </div>

        <button className='btn btn-dark' type="submit">Add Item</button>

       </div>

      </form>

      <br />

      <div className='todoListContainer'>

       {

        todoList.map((item, index) => {

         return (

          <div key={index}>

           <TodoList

            id={item.id}

            index={index}

            title={item.title}

            timeSubmitted={item.timeSubmitted}

            completed={item.completed}

            //Passing States

            todoList={todoList}

            setTodoList={setTodoList}

            isCompleted={isCompleted}

            setIsCompleted={setIsCompleted}

           />

          </div>

         )

        })

       }

      </div>

     </div>

    </div>

   </div>

   <Footer />

  </div>

 )

}

export default Home;

Теперь в каталоге styles создайте новую папку с именем ContainerCss, а затем в папке ContainerCss создайте файл с именем Home.css. Таким образом, это будет путь styles\ContainerCss\Home.css. Затем напишите в этом файле следующий код CSS.

/* styles\ContainerCss\Home.css */

.form_styling {
    width: 70%;
    background-color: #f2f2f2;
    padding: 20px;
    border-radius: 10px;
    margin: 0 auto;
}
.addItemInput {
    width: 85%;
    margin-right: 1%;
}
.todoListContainer{
    width: 70%;
    background-color: #dbd8f0;
    padding: 20px;
    border-radius: 10px;
    margin: 0 auto;
}

Примечание. В настоящее время, если вы будете запускать интерфейсную часть. Это приведет к ошибкам, потому что компоненты еще не созданы, поэтому следуйте за мной, и вы будете в курсе.

Итак, теперь давайте создадим компоненты

Создание компонентов

Во-первых, мы начнем с компонента заголовка.

  1. Заголовок

Сначала мы создадим компонент с именем Header. Итак, в корне создайте папку с именем «Компоненты», а затем в этой папке создайте еще одну папку с именем «Заголовок». Теперь создайте файл внутри этой папки с именем index.jsx. Таким образом, путь будет Components\Header\index.jsx. Теперь напишите в этом файле следующий код.

const Header = () => {
    return (
        <>
            {/* Navbar */}
            <nav className="navbar navbar-expand-lg navbar-light bg-light">
                {/* Container wrapper */}
                <div className="container-fluid">
                    {/* Toggle button */}
                    <button className="navbar-toggler" type="button" data-mdb-toggle="collapse" data-mdb-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <i className="fas fa-bars" />
                    </button>
                    {/* Collapsible wrapper */}
                    <div className="collapse navbar-collapse" id="navbarSupportedContent">
                        {/* Navbar brand */}
                        <a className="navbar-brand mt-2 mt-lg-0" href="#">
                            <img src="/logo.png" height={45} title="Redis :) The most loved developers database." alt="Redis" loading="lazy" />
                        </a>
                        {/* Left links */}
                        <ul className="navbar-nav fill me-auto mb-2 mb-lg-0">
                            <li className="nav-item">
                                <a className="nav-link" href="#">Home</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Learn Redis" href="https://university.redis.com/">Learn Redis</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Try Redis" href="https://redis.com/try-free/">Try Redis</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Get Certified" href="https://university.redis.com/certification/">Get Certified</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Find Redis" href="https://www.linkedin.com/company/redisinc/">Find Redis</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Redis Users" href="https://redis.io/docs/about/users/">Redis Users</a>
                            </li>
                            <li className="nav-item">
                                <a className="nav-link" target="_blank" title="Redis is one of the most loved database on stack overflow survey.Lets check" href="https://insights.stackoverflow.com/survey/2021#most-loved-dreaded-and-wanted-database-love-dread">Most Loved</a>
                            </li>
                        </ul>
                        {/* Left links */}
                    </div>
                    {/* Collapsible wrapper */}
                    {/* Right elements */}
                    <div className="d-flex align-items-center">
                        {/* Icon */}
                        <a className="text-reset me-3" title="Learn With Redis University" target="_blank" href="https://university.redis.com/">
                            <img src="https://download.logo.wine/logo/Redis/Redis-Logo.wine.png" className="rounded-circle" height={50} alt="Muhammad Bilal" title="Muhammad Bilal" loading="lazy" />
                        </a>
                        {/* Avatar */}
                        <div className="dropdown">
                            <a className="dropdown-toggle d-flex align-items-center hidden-arrow" href="#" id="navbarDropdownMenuAvatar" role="button" data-mdb-toggle="dropdown" aria-expanded="false">
                                <img src="https://media-exp2.licdn.com/dms/image/C4D03AQEXk-Oc_il_Jw/profile-displayphoto-shrink_200_200/0/1624098249818?e=1661385600&v=beta&t=0-YbW3xzYac9E5BEJJ0ShrHJsDOfw2XXoVAyfSpDhmE" className="rounded-circle" height={25} alt="Muhammad Bilal" title="Muhammad Bilal" loading="lazy" />
                            </a>
                            <ul className="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuAvatar">
                                <li>
                                    <a className="dropdown-item" title="Linkedin Profile" href="https://www.linkedin.com/in/muhammad-bilal-028843199/">Linkedin</a>
                                </li>
                                <li>
                                    <a className="dropdown-item" title="Github Profile" href="https://github.com/Muhammad-Bilal-7896/">Github</a>
                                </li>
                                <li>
                                    <a className="dropdown-item" title="Email" href = "mailto:[email protected]">[email protected]</a>
                                </li>
                            </ul>
                        </div>
                    </div>
                    {/* Right elements */}
                </div>
                {/* Container wrapper */}
            </nav>
            {/* Navbar */}


        </>
    )
}
export default Header;

Примечание. Заглавные страницы и ссылки полностью зависят от вас. Даже заголовок является необязательным. Самое главное — это фронтенд и бэкэнд. Верхний и нижний колонтитулы необязательны.

  • Теперь создайте другой файл в той же папке Header с именем style.css. Таким образом, его путь будет Components\Header\style.css. Здесь напишите следующий фрагмент CSS.
/* Components\Header\style.css */
.nav-link,
.nav-link:after,
.nav-link:before {
    transition: all .5s !important;
}

.nav-link {
    border-bottom: 1px solid transparent !important;
}

.nav-link:hover {
    color: rgb(236, 28, 56) !important;
    border-bottom: 1px solid rgb(236, 28, 56) !important;
    transition: 0.5s linear !important;
}

Примечание. Следует помнить, что все файлы CSS должны быть импортированы в файл app.js, но мы сделаем это в конце, после того как создадим все файлы CSS.

2. Нижний колонтитул

  • Теперь снова внутри папки компонентов, расположенной в корне, создайте файл с именем Footer. Теперь создайте в этой папке файл с именем index.jsx. Его относительный путь будет Components\Footer\index.jsx. Напишите следующий код.
// Components\Footer\index.jsx
const Footer = () => {
    return (
        <div className="footer">
            <div className="container">
                <div className="row">
                    <div className="col-md-12">
                        <p>Copyright &copy; 2022 TodoAppNextJSRedis By <a target="_blank" href="https://github.com/Muhammad-Bilal-7896/">Muhammad Bilal</a></p>
                    </div>
                </div>
            </div>
        </div>
    )
}
export default Footer;
  • Теперь создайте файл с именем style.css в той же папке, то есть в папке нижнего колонтитула. Путь к файлу будет Components\Footer\style.css. Теперь напишите следующий фрагмент CSS.
/* Components\Footer\style.css */
.footer {
    background-color: #f5f5f5;
    padding: 20px;
    margin-top: 20px;
    line-height: 50px;
    height: 80px;
    border:"1px solid #e5e5e5";
}

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

3) Список дел

  • Снова внутри папки «Компоненты» создайте папку с именем «Главная». Внутри домашней папки создайте еще одну папку с именем TodoList. Затем внутри папки TodoList создайте файл с именем index.jsx. Теперь путь к этому файлу будет таким: Components\Home\TodoList\index.jsx. Теперь напишите следующий код внутри этого файла.
import { useState } from "react";


const TodoList = (props) => {

    //Destructing the props object to get the props in variables
    const { id, index, title, completed, timeSubmitted, setTodoList, todoList, isCompleted, setIsCompleted } = props;


    const [isEdit, setIsEdit] = useState(false);


    const [editValue, setEditValue] = useState(title);


    //Methods
    const triggerUpdateToCloud = async (uniqueId, type) => {
        if (editValue !== "") {
            if (type === "markComplete") {
                // alert(`Triggering Update to Cloud with the value: ${editValue}`);
                await fetch(`http://localhost:8000/todo/${uniqueId}`, {
                    method: "PUT",
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        completed: !completed,
                        title: editValue,
                        timeSubmitted: timeSubmitted
                    })
                });
                let tempList = []
                for (let i = 0; i < todoList.length; i++) {
                    let tempObj = todoList[i];
                    if (todoList[i].id === uniqueId) {
                        tempObj = { ...tempObj, completed: !completed }
                    }
                    tempList.push(tempObj);
                }
                setTodoList(tempList);
                setIsEdit(false);
            }
            else if (type === 'triggerUpdate') {
                const response = await fetch(`http://localhost:8000/todo/${uniqueId}`, {
                    method: "PUT",
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        completed: completed,
                        title: editValue,
                        timeSubmitted: new Date().toLocaleString()
                    })
                });
                let tempList = []
                for (let i = 0; i < todoList.length; i++) {
                    let tempObj = todoList[i];
                    if (todoList[i].id === uniqueId) {
                        tempObj = { ...tempObj, title: editValue }
                    }
                    tempList.push(tempObj);
                }
                setTodoList(tempList);
                setIsEdit(false);
            }
            else {
                console.warn("Please look at your function arguements.Make them correct.")
            }
        }
        else {
            alert("Please enter a value to update");
        }
    }


    const deleteTodo = async uniqueId => {
        if (window.confirm('Are you sure you want to delete this task?')) {
            await fetch(`http://localhost:8000/todo/${uniqueId}`, {
                method: 'DELETE'
            });


            setTodoList(todoList.filter(t => t.id !== uniqueId));
        }
    }


    return (
        <div className="todoList">
            {(todoList.length !== 0) ? (
                <div>
                    <div>
                        {
                            (isEdit) ? (
                                <input type="text" value={editValue} onChange={(e) => setEditValue(e.target.value)} className="form-control" />
                            ) : (
                                (!completed) ? (
                                    <h3>
                                        {index + 1}- {title}
                                    </h3>
                                ) : (
                                    <h3 className="text-success">
                                        <del>{index + 1}- {title}</del>
                                    </h3>
                                ))
                        }
                    </div>
                    <div className="d-flex mt-4 justify-content-between">
                        <h6 className="mt-2">{timeSubmitted}</h6>
                        <div className="d-flex justify-content-between">
                            {
                                (!isEdit) ? (
                                    <button style={{ marginRight: "10px" }} className="btn btn-warning" onClick={() => setIsEdit(true)}>Edit</button>
                                ) : (
                                    <button style={{ marginRight: "10px" }} className="btn btn-success" onClick={() => triggerUpdateToCloud(id, "triggerUpdate")}>Update</button>
                                )
                            }
                            <button style={{ marginRight: "10px" }} className="btn btn-danger" onClick={() => deleteTodo(id)}>Delete</button>
                            {
                                (!completed) ? (
                                    <button className="btn btn-success" onClick={() => triggerUpdateToCloud(id, "markComplete")}>Mark Complete</button>
                                ) : (
                                    <button className="btn btn-primary" onClick={() => triggerUpdateToCloud(id, "markComplete")}>Mark Incomplete</button>
                                )
                            }
                        </div>
                    </div>
                </div>
            ) : (
                <h3 className="text-center">No Tasks to Display</h3>
            )}
        </div>
    )
}
export default TodoList;
  • Находясь в той же папке TodoList, создайте файл с именем style.css. Так, чтобы его путь был таким: Components\Home\TodoList\style.css. Теперь напишите следующий код внутри этого файла.
/* Components\Home\TodoList\style.css */

.todoList{
    width: 100%;
    height: 100%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 5px #000;
    padding: 10px;
    overflow: hidden;
    margin-top: 5px;
}

Импорт наших файлов CSS в файл app.js

  • Теперь пришло время импортировать все наши файлы CSS, чтобы стили можно было применить к нашему приложению. Для этого перейдите к этому файлу pages\_app.js и добавьте следующий код после предыдущего импорта.
// pages\ _app.js

//Importing Containers CSS Files
import '../styles/globals.css';
import "../styles/ContainerCss/Home.css";


//Importing Component CSS Files
import "../Components/Home/TodoList/style.css";
import "../Components/Footer/style.css";
import "../Components/Header/style.css";

Полный _app.js будет выглядеть так.

// pages\ _app.js

import Head from 'next/head'
import Script from 'next/script';

//Importing Containers CSS Files
import '../styles/globals.css';
import "../styles/ContainerCss/Home.css";

//Importing Component CSS Files
import "../Components/Home/TodoList/style.css";
import "../Components/Footer/style.css";
import "../Components/Header/style.css";

function MyApp({ Component, pageProps }) {
  return <>
    <Head>
      <meta charSet="utf-8" />
      <meta name="description" content="A todo app built with Next JS,redis,Node JS and Express" />
      <meta name="keywords" content="TodoApp,NextJS,Redis,NodeJS,Express,Realtime" />
      <meta name="author" content="Muhammad-Bilal-7896" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />


      <title>NextJSRedisTodoApp</title>
    </Head>
    <Component {...pageProps} />
    <Script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.5.0/mdb.min.js"
    ></Script>
  </>
}
export default MyApp;

На этом наш внешний интерфейс завершен, и теперь пришло время написать наш внутренний код.

Написание backend части.

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

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

Теперь создайте здесь папку с именем backendtodoappnextjsredis. Затем откройте cmd (или терминал, если вы работаете в Linux) и напишите следующую команду, чтобы инициализировать пустой проект js.

npm init

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

Примечание. Важно выбрать в качестве точки входа файл index.js. Это будет по умолчанию. Вам просто нужно нажать Enter, отвечая на вопросы.

В конце он спросит вас, все ли в порядке. Вам просто нужно нажать Enter.

Теперь после этого файл с именем package.json. Теперь мы изменим этот файл для нашего удобства и варианта использования.

Отредактируйте файл package.json в соответствии со следующими настройками. Мы добавили команду запуска в сценарий и тип «модуль». Другие вещи, такие как описание, ключевые слова, автор и лицензия, зависят от вашего собственного выбора. Вы хотели бы написать имя автора как ваше. Так что не забудьте это сделать. Но помните, не редактируйте объект скриптов по своему выбору. Вы можете, но только если вы считаете, что имеете на это право.

{
  "name": "backendtodoappnextjsredis",
  "version": "1.0.0",
  "description": "Backend based in redis database and nodejs and express",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "redis",
    "nodejs",
    "expressjs"
  ],
  "author": "Muhammad-Bilal-7896",
  "license": "MIT"
}

Итак, теперь в корневой папке серверной части, где вы открыли cmd для создания файла JSON. В том же cmd или терминале введите следующую команду для установки пакетов.

Мы установим следующие пакеты

  • редис-ом
  • Корс
  • экспресс
  • узел

Итак, введите следующую команду и нажмите Enter.

npm i cors express nodemon redis-om

Это будет выглядеть так в cmd.

После установки модулей узла. Теперь пришло время написать наш внутренний код.

  • В корне бэкенда создайте папку с именем src. Затем внутри этой папки создайте еще одну папку с именем schema. Теперь внутри папки схемы создайте файл с именем task.schema.js. Этот файл будет содержать нашу схему для серверной части Redis. Относительный путь к этому файлу из корневой папки бэкенда будет следующим: src\schema\task.schema.js. Добавьте в этот файл следующий код.
import {Entity, Schema} from "redis-om";


class Todo extends Entity {
    toJSON() {
        return {
            //Note: Remember here the entities you are adding you have to keep the pattern same everywhere.You can change add more entities or offcourse remove some of them
            id: this.entityId,
            title: this.title,
            timeSubmitted: this.timeSubmitted,
            completed: this.completed
        }
    }
}

//Note: Remember here the taskSchema you are adding you have to keep the pattern same everywhere.You can change add more entities or offcourse remove some of them
export const taskSchema = new Schema(Todo, {
    title: {
        type: 'string'
    },
    timeSubmitted:{
        type: 'string'
    },
    completed: {
        type: 'boolean'
    }
}, {
    dataStructure: 'JSON'
});
  • Теперь в папке src создайте файл с именем index.js. Добавьте в этот файл следующий код.
import express from 'express'
import cors from 'cors';
import { Client, Repository } from "redis-om";
import { taskSchema } from "./schema/task.schema.js";

const app = express();
app.use(express.json());
app.use(cors({
    origin: ['http://localhost:3000']
}));


//Note: I will explain how you can get your endpoint below.Add your username,endpoint and password here
let username = "bilal";
let password = "Your Password"
let endPoint = "redis-15666.c98.us-east-1-4.ec2.cloud.redislabs.com:15666";


const client = new Client();
await client.open(`redis://${username}:${password}@${endPoint}`);

// const taskRepository = new Repository(taskSchema, client);
const taskRepository = client.fetchRepository(taskSchema)


await taskRepository.dropIndex();
await taskRepository.createIndex();


app.get('/todo', async (req, res) => {
    res.send(await taskRepository.search().returnAll());
});


app.post('/todo', async (req, res) => {
    const todo = taskRepository.createEntity();


    todo.title = req.body.title;
    todo.timeSubmitted = req.body.timeSubmitted;
    todo.completed = req.body.completed;
    todo.id = await taskRepository.save(todo);


    res.send(todo);
});


app.put('/todo/:id', async (req, res) => {
    const todo = await taskRepository.fetch(req.params.id);


    //Update values
    todo.title = req.body.title;
    todo.completed = req.body.completed;
    todo.timeSubmitted = req.body.timeSubmitted;


    await taskRepository.save(todo);


    res.send(todo);
});


app.delete('/todo/:id', async (req, res) => {
    await taskRepository.remove(req.params.id);


    res.send(null);
});


app.listen(8000, () => {
    console.log("Redis Backend started on port 8000...");
});

Добавление имени пользователя, пароля и конечной точки:

  • Теперь в строке № 12, как я уже сказал, вам нужно добавить свое имя пользователя, пароль и конечную точку базы данных. Но не волнуйтесь, я объясню каждый шаг. Теперь перейдите к своей Redis Cloud Console. Здесь авторизуйтесь и вы будете перенаправлены на эту страницу.

  • Теперь в верхнем левом углу расположена боковая панель. Перейдите на вкладку базы данных, и вы увидите этот экран.

  • Теперь нажмите кнопку копирования, расположенную в 5-м столбце отображаемой информации, чтобы скопировать конечную точку базы данных. Как показано ниже.

  • Это даст вам конечную точку базы данных. Вы должны вставить эту конечную точку в строку № 15 самого последнего файла кода src\index.js. Так
let endPoint = "Your copied endpoint";
  • Теперь имя пользователя и пароль вы можете выбрать на вкладке управления доступом к данным. Как я уже говорил ранее, вы должны помнить и хранить свой пароль в надежном месте. Потому что вы не можете его просмотреть. Если вы его забудете. Вы можете изменить это. Замените имя пользователя и пароль на свои в строках 13 и 14.
let username = "Your username"
let password = "Your password";
  • Вы можете получить их здесь, а также, если вы забыли свой пароль, вы можете изменить его здесь.
  • Как только вы наведете курсор на пароль, он покажет вам возможность удаления и редактирования. Поэтому, если вы хотите изменить свой пароль, нажмите «Изменить», расположенный справа рядом с опцией удаления.

Поздравляем с успехом. Это означает, что вы заинтересованы в изучении новых технологий и концепций. Теперь, после этого, мы закончили с нашей внутренней частью. Теперь пришло время запустить наше приложение.

Запуск нашего TodoApp: -

Теперь пришло время, наконец, начать наш проект. Сначала мы запустим наш внутренний сервер.

1) Запуск внутреннего сервера

  • Чтобы начать это. Просто перейдите в корень внутренней папки и напишите следующую команду.
npm start
  • Выглядит так в cmd.

  • Сообщение: Redis Backend запущен на порту 8000… будет отображаться на терминале, если серверная часть работает без ошибок.
  • Вы можете просмотреть данные в базе данных, перейдя по следующему URL-адресу API.

http://локальный:8000/todo

2) Запускаем наш интерфейс

  • Теперь перейдите в корень внешнего интерфейса следующего проекта js и запустите проект, открыв терминал или cmd в корне папки внешнего интерфейса. Введите следующую команду, чтобы запустить наш следующий интерфейс js.
npm run dev

и проект будет запущен на http://localhost:3000/

Если вы правильно выполнили все шаги, вы сможете добавить задачу в базу данных, и вы должны увидеть, что она работает.

Примечание о Redis Insight (необязательно):

Redis Insight можно скачать отсюда. Скачать Redis Insight

RedisInsight – это диспетчер рабочего стола с интуитивно понятным и эффективным графическим интерфейсом для Redis, который позволяет вам взаимодействовать с базами данных, отслеживать данные и управлять ими.

Это даст вам возможность просматривать базу данных Redis и управлять ею непосредственно из приложения Redis Insight.

Просмотр нашей базы данных Redis в RedisInsight.

  • После загрузки и установки RedisInsight вы увидите следующее представление:

  • Теперь нажмите кнопку ДОБАВИТЬ БАЗУ ДАННЫХ REDIS, расположенную в центре внизу. Теперь вы увидите этот вид.

  • Теперь выберите Добавить базу данных вручную.
  • Затем в Host Input вставьте скопированную конечную точку из консоли Redis. Вы можете еще раз скопировать конечную точку из консоли Redis, как я уже говорил вам ранее. После копирования вставьте в поле ввода Host, как показано ниже.

Порт и псевдоним базы данных будут автоматически заполнены RedisInsight. Так что не беспокойтесь о них. Также введите имя пользователя и пароль.

Теперь в правом нижнем углу нажмите кнопку Добавить базу данных Redis. База данных будет добавлена ​​в ваш RedisInsight.

Если база данных была успешно добавлена, она покажет вам подтверждающее сообщение.

Теперь вы можете нажать на базу данных, чтобы просмотреть ее. Появится что-то вроде этого.

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

Ознакомьтесь со следующими полезными ссылками

Спасибо за прочтение!

С уважением

Мухаммад Билал