Как создать приложение To-do с помощью Next.js и Strapi

Обновлено в июле 2023 г.

В этой статье мы научимся использовать Strapi, Next.js и GraphQL для создания простого приложения для создания дел.

Что такое Страпи?

Strapi — это самая передовая автономная система управления контентом Node.js с открытым исходным кодом, используемая для быстрого и эффективного создания масштабируемых, безопасных, готовых к использованию API, экономящих разработчикам бесчисленные часы работы. разработка. Благодаря расширяемой системе плагинов он предоставляет огромный набор встроенных функций: панель администратора, управление аутентификацией и разрешениями, управление контентом, генератор API и т. д. Strapi на 100 % имеет открытый исходный код, что означает :

  • Strapi полностью бесплатен.
  • Вы можете разместить его на своих серверах, чтобы данные принадлежали вам.
  • Он полностью настраиваем и расширяем благодаря системе плагинов.

Что такое Next.js?

Next.js — это легкая платформа React для создания приложений, отображаемых на сервере. Next.js возьмет на себя тяжелую работу по сборке приложения, такую ​​как разделение кода, HMR (горячая замена модулей) SSR (рендеринг на стороне сервера), и позволит нам сосредоточиться на написании кода, а не на написании кода. наша конфигурация сборки.

Что такое GraphQL?

GraphQL — это язык запросов, который позволяет интерфейсу приложения легко запрашивать API приложения. Каждый запрос запрашивает только те данные, которые необходимо отобразить текущим представлением. Это позволяет разработчику обеспечить удобство работы с пользователем на множестве устройств и размеров экрана.

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

Например, у нас есть книжный ресурс: /books. Глаголы HTTP обозначают действие, которое необходимо выполнить с ресурсами книги. Книги становятся коллекцией, и можно добавить новую книгу, отредактировать книгу и удалить книгу.

Следующий запрос CRUD можно выполнить к ресурсу книги, используя:

  • ПОСТ api/books
  • ПОЛУЧИТЕ api/books и api/books/:id, чтобы получить конкретную книгу
  • ПОСТАВИТЬ api/books/:id
  • УДАЛИТЬ api/books/:id

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

Предварительные условия

Чтобы эффективно следовать этой статье, убедитесь, что у вас есть:

  • Node.js: поддерживаются только версии Maintenance и LTS (v14, v16 и v18).
  • Узел v18.x рекомендуется для Strapi v4.3.9 и выше.
  • Узел v16.x рекомендуется для Strapi от v4.0.x до v4.3.8.
  • Менеджер пакетов, желательно Пряжа.
  • Вы можете установить пряжу, используя npm i -g yarn, которая установит пряжу глобально.
  • Базовые знания NextJS.
  • Редактор кода, желательно Visual Studio Code.

Теперь, когда все готово, мы можем приступить к созданию приложения to-do.

Настройка Страпи

Прежде чем мы сможем настроить Strapi, нам нужно создать папку, содержащую исходный код. Откройте терминал в нужном каталоге и запустите приведенный ниже код:

mkdir strapi-todo-blog
  cd strapi-todo-blog

Затем откройте папку strapi-todo-blog в Visual Studio Code. Теперь мы можем запустить следующие строки кода во встроенном терминале Vs Code для установки Strapi.

npx create-strapi-app@latest todo-api --quickstart

После успешной установки вы получите сообщение об успешной установке, подобное приведенному ниже:

Далее вы будете перенаправлены на страницу администратора. Здесь вы создадите своего первого администратора. Заполните запрошенную информацию и нажмите кнопку Начать.

Если вы не были перенаправлены и приложение Strapi не запущено на вашем терминале, запустите Strapi с помощью yarn develop и вручную перейдите к http://localhost:1337/admin/auth/register-admin

Нажатие на кнопку создаст вашу панель администратора, как показано ниже:

Создание коллекций

Теперь мы создадим веб-ресурсы. Перейдите к Content-Types Builder и нажмите Create new collection тип. Появится модальное окно, введите todo в качестве Отображаемого имени и нажмите Продолжить.

Появится модальное окно, в котором мы выбираем поле для нашего типа коллекции. Нажмите на Text.

Введите todoText и нажмите кнопку Готово ****.

Создав поле todoText, нажмите Сохранить в правом верхнем углу. Это приведет к перезагрузке сервера Strapi. После успешного перезапуска Strapi нажмите Диспетчер контента на боковой панели навигации, выберите тип коллекции todo и Создайте новую запись. .

Затем введите задачу в todoText, нажмите «Сохранить», а затем нажмите «Опубликовать».

Задача будет похожа на приведенную ниже и будет содержать TODOTEXT, CREATEDAT, UPDATEDAT и STATE:

Включение доступа

Strapi предназначен для обеспечения безопасности вашего приложения путем ограничения доступа к различным конечным точкам API. Выполнение запроса CRUD к типу коллекции todo без предоставления разрешения приведет к ошибке 403 Forbidden, как показано ниже.

В Strapi есть две роли, которым можно предоставить разрешение.

  • Аутентифицированные пользователи: для пользователей, вошедших в систему.
  • Публичный (неавторизованные пользователи): для пользователей, не вошедших в систему.
  • Из-за простоты этого приложения мы не будем разрабатывать систему входа в систему. Не стесняйтесь проверить эту статью, чтобы создать ее.

Чтобы предоставить доступ:

  • Перейдите в Настройки, затем Роли и разрешения.
  • Нажмите на роль Public.
  • Откройте аккордеон, который находится в разделе Todo.
  • Установите флажок Select all.
  • Нажмите Сохранить в правом верхнем углу.

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

Включение GraphQL

По умолчанию API, созданные с помощью Strapi, являются конечными точками REST. Конечные точки можно легко интегрировать в конечные точки GraphQL с помощью встроенного плагина GraphQL. Чтобы установить GraphQL в приложение, откройте папку todo-api в своем терминале и запустите строку кода ниже:

npm install @strapi/plugin-graphql

После успешной установки перезапустите сервер Strapi, перейдите по адресу http://localhost:1337/graphql и попробуйте выполнить следующий запрос:

query Todo {
  todos {
    data {
      id
      attributes {
        todoText
      }
    }
  }
}

Вы должны получить результат, аналогичный приведенному ниже.

Создание приложения Next.js

Мы создали API Strapi, и следующим шагом будет создание интерфейса.

Убедитесь, что вы находитесь в каталоге strapi-todo-blog.

Откройте свой терминал в каталоге strapi-todo-blog и запустите приведенный ниже код, чтобы установить NextJS.

npx create-next-app@latest todo-app

При запуске команды create-next-app вам будет задано несколько вопросов. Следуйте инструкциям и ответьте в зависимости от ваших предпочтений или как показано ниже:

Настройка Аполло

В этом уроке мы будем использовать Apollo Client для подключения нашего приложения NextJS к конечной точке Grapi Grapi. Откройте свой терминал в папке todo-app и запустите приведенный ниже код, который установит все зависимости, необходимые для работы Apollo:

npm install @apollo/client@alpha @apollo/experimental-nextjs-app-support --legacy-peer-deps

Теперь создайте папку в каталоге src с именем lib и создайте в ней файл с именем client.tsx. После создания файла мы применим логику Apollo во вновь созданном файле.

// src/lib/client.tsx
"use client";
import { HttpLink, SuspenseCache, ApolloLink } from "@apollo/client";
import {
  NextSSRApolloClient,
  ApolloNextAppProvider,
  NextSSRInMemoryCache,
  SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
const STRAPI_URL = process.env.STRAPI_URL || "http://localhost:1337";
function makeClient() {
  const httpLink = new HttpLink({
    uri: `${STRAPI_URL}/graphql`,
  });
  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  });
}
function makeSuspenseCache() {
  return new SuspenseCache();
}
export function ApolloWrapper({ children }: React.PropsWithChildren) {
  return (
    <ApolloNextAppProvider
      makeClient={makeClient}
      makeSuspenseCache={makeSuspenseCache}
    >
      {children}
    </ApolloNextAppProvider>
  );
}

Выше мы создали поставщика Apollo-wrapper. Этот поставщик будет обертывать React.ReactNode (children), позволяя Apollo работать со всеми клиентскими компонентами приложения. Далее мы импортируем поставщика Apollo-wrapper в файл layout.tsx.

// src/app/layout.tsx
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ApolloWrapper } from "@/lib/client"; //Importing the ApolloWrapper Provider
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
  title: "Todo app",
  description: "Generated by Fredrick Emmanuel",
};
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className} suppressHydrationWarning={true}>
        <ApolloWrapper>
          {/* Wrapping the React.ReactNode*/}
          {children}
        </ApolloWrapper>
      </body>
    </html>
  );
}

Не стесняйтесь проверить эту статью для справки.

Настройка внешнего интерфейса

Наше приложение todo будет выглядеть так:

Мы разделим его на различные составляющие:

Разделы Header и TodoItem будут находиться в папке components, а AddTodo и TodoList — в папке containers. Создайте новую папку с именем components в каталоге src и создайте два файла: Header.tsx и TodoItem.tsx. Затем создайте еще одну папку в каталоге src с именем containers и создайте два файла: AddTodo.tsx и Todolist.tsx. Ваш каталог src должен выглядеть так:

📂src
┃ ┣ 📂app
┃ ┃ ┣ 📜favicon.ico
┃ ┃ ┣ 📜globals.css
┃ ┃ ┣ 📜layout.tsx
┃ ┃ ┣ 📜page.module.css
┃ ┃ ┗ 📜page.tsx
┃ ┣ 📂components
┃ ┃ ┣ 📜Header.tsx
┃ ┃ ┗ 📜TodoItem.tsx
┃ ┣ 📂containers
┃ ┃ ┣ 📜AddTodo.tsx
┃ ┃ ┗ 📜TodoList.tsx
┃ ┗ 📂lib
┃ ┃ ┗ 📜client.tsx

Давайте конкретизируем файлы: откройте файл globals.css и замените в нем код кодом ниже:

/* src/app/globals.css */
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-size: xx-large;
}
a {
  color: inherit;
  text-decoration: none;
}
* {
  box-sizing: border-box;
}
.main {
  padding: 10px 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.header {
  display: flex;
  justify-content: center;
  color: rgba(70, 130, 236, 1);
}
.todoInputText {
  padding: 10px 7px;
  border-radius: 3px;
  margin-right: 2px;
  margin-left: 2px;
  width: 100%;
  font-size: large;
}
button {
  padding: 10px 10px;
  border-radius: 3px;
  cursor: pointer;
  margin-right: 2px;
  margin-left: 2px;
  font-size: large;
}
.bg-default {
  background-color: rgba(70, 130, 236, 1);
  border: 1px solid rgba(28, 28, 49, 1);
  color: white;
}
.bg-danger {
  background-color: red;
  border: 1px solid rgba(28, 28, 49, 1);
  color: white;
}
.todoInputButton {
  padding: 10px 10px;
  border-radius: 3px;
  background-color: rgba(70, 130, 236, 1);
  color: white;
  border: 1px solid rgba(28, 28, 49, 1);
  cursor: pointer;
  margin-right: 2px;
  margin-left: 2px;
  font-size: large;
}
.addTodoContainer {
  margin-top: 4px;
  margin-bottom: 17px;
  width: 500px;
  display: flex;
  justify-content: space-evenly;
}
.todoListContainer {
  margin-top: 9px;
  width: 500px;
}
.todoItem {
  padding: 10px 4px;
  color: rgba(70, 130, 236, 1);
  border-radius: 3px;
  border: 1px solid rgba(28, 28, 49, 1);
  margin-top: 9px;
  margin-bottom: 2px;
  display: flex;
  justify-content: space-between;
}
.todosText {
  padding-bottom: 2px;
  border-bottom: 1px solid;
}

Затем откройте файл Header.tsx и добавьте следующее:

// src/components/Header.tsx
export default function Header() {
  return (
    <div className="header">
      <h2>ToDo app</h2>
    </div>
  );
}

Теперь мы импортируем компонент Header и разместим его над React.ReactNode в файле layout.tsx.

// src/app/layout.tsx
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ApolloWrapper } from "@/lib/client"; //Importing the ApolloWrapper Provider
const inter = Inter({ subsets: ["latin"] });
import Header from "@/components/Header";

//The rest of the code

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className} suppressHydrationWarning={true}>
        <ApolloWrapper>
          {/* Wrapping the React.ReactNode*/}
          <Header />
          {/* Header */}
          {children}
        </ApolloWrapper>
      </body>
    </html>
  );
}

В AddTodo.tsx добавьте:

// src/container/AddTodo.tsx
import { useState } from "react";
function AddTodo({ addTodo }: { addTodo: FunctionStringCallback }) {
  const [todo, setTodo] = useState<string>("");
  return (
    <>
      <div className="addTodoContainer">
        <input
          className="todoInputText"
          type="text"
          placeholder="Add new todo here..."
          id="todoText"
          value={todo}
          onChange={(e) => {
            setTodo(e.target.value);
          }}
          onKeyDown={(e) => {
            if (e.code === "Enter") {
              addTodo(todo);
              setTodo("");
            }
          }}
        />
        <input
          className="todoInputButton"
          type="button"
          value="Add Todo"
          onClick={() => {
            addTodo(todo);
            setTodo("");
          }}
        />
      </div>
    </>
  );
}
export default AddTodo;

На основе приведенного выше кода мы извлекли функцию addTodo из props и вызывали ее при нажатии Enter или при нажатии кнопки Add Todo. Эта функция отправляет значение ввода (todo), используя передачу реквизита от дочернего элемента к родительскому. Откройте файл TodoItem.tsx и добавьте в него следующее:

// src/coomponents/TodoItem.tsx
interface ItemTodo {
  todo: any;
  editTodoItem: FunctionStringCallback;
  deleteTodoItem: FunctionStringCallback;
}
function TodoItem({ todo, editTodoItem, deleteTodoItem }: ItemTodo) {
  return (
    <>
      <div className="todoItem">
        <div>{todo.attributes.todoText}</div>
        <div>
          <i>
            <button className="bg-default" onClick={() => editTodoItem(todo)}>
              Edit
            </button>
          </i>
          <i>
            <button className="bg-danger" onClick={() => deleteTodoItem(todo)}>
              Del
            </button>
          </i>
        </div>
      </div>
    </>
  );
}
export default TodoItem;

В приведенном выше коде отображается каждый элемент списка дел, состоящий из кнопок todoText, Edit и Del. Затем импортируйте TodoItem в файл TodoList.tsx.

// src/containers/TodoList.tsx
import TodoItem from "@/components/TodoItem";
interface ListTodo {
  todos: any;
  editTodoItem: any;
  deleteTodoItem: any;
}
function TodoList({ todos, editTodoItem, deleteTodoItem }: ListTodo) {
  return (
    <div className="todoListContainer">
      <div className="todosText">Todos</div>
      {todos
        ?.sort((a: any, b: any) =>
          b.attributes.createdAt.localeCompare(a.attributes.createdAt)
        )
        .map((todo: any) => {
          return (
            <TodoItem
              todo={todo}
              key={todo.id}
              deleteTodoItem={deleteTodoItem}
              editTodoItem={editTodoItem}
            />
          );
        })}
    </div>
  );
}
export default TodoList;

Этот код проходит через todos и отображает каждый TodoItem. Наконец, мы импортируем файлы AddTodo.tsx и TodoList.tsx в файл pages.tsx и передадим соответствующие реквизиты.

// src/app/page.tsx
"use client";
import { useEffect, useState } from "react";
import AddTodo from "@/containers/AddTodo";
import TodoList from "@/containers/TodoList";
export default function Home() {
  const [todos, setTodos] = useState<[]>([]);
  const addTodo = async (todoText: string) => {};
  const editTodoItem = async (todo: any) => {
    console.log("Edited");
  };
  const deleteTodoItem = async (todo: any) => {
    console.log("Deleted");
  };
  return (
    <div>
      <main className="main">
        <AddTodo addTodo={addTodo} />
        <TodoList
          todos={todos}
          deleteTodoItem={deleteTodoItem}
          editTodoItem={editTodoItem}
        />
      </main>
    </div>
  );
}

Создание CRUD-запросов

Мы подошли к основной части этого урока. В этом разделе мы займемся

  • Получение всех задач
  • Создание задачи
  • Редактирование задач и
  • Удаление задачи из Headless CMS Strapi.

Начнем 🎉 .

Получение всех задач

Создайте в каталоге src папку с именем query, создайте файл с именем Schema.tsand add the following lines of code to theschema.ts`.

// src/query/schema.ts
import { gql } from "@apollo/client";
export const GETQUERY = gql`
  {
    todos(sort: "id:desc") {
      data {
        id
        attributes {
          todoText
          createdAt
        }
      }
    }
  }
`;

Выше мы получим все новейшие данные, используя sort: "id:desc".

Файл schema.ts будет содержать схему для всех запросов Graphql.

Затем импортируйте GETQUERY и useQuery в файл page.tsx:

// src/app/page.tsx
"use client";
import { useEffect, useState } from "react";
import AddTodo from "@/containers/AddTodo";
import TodoList from "@/containers/TodoList";
import { useQuery } from "@apollo/experimental-nextjs-app-support/ssr";
import { GETQUERY } from "@/query/schema";

export default function Home() {
  const [todos, setTodos] = useState<[]>([]);
  const { loading, error, data } = useQuery(GETQUERY, {
    fetchPolicy: "no-cache",
  }); //Fetching all todos
  useEffect(() => {
    setTodos(data?.todos?.data); //Storing all the todos
  }, [data]);

  //rest of the code
}

Здесь мы получили все задачи из Strapi с помощью useQuery и сохранили их в состоянии todos. Перейдите по адресу http://localhost:3000, и вы должны получить результат, аналогичный приведенному ниже:

Strapi по умолчанию устанавливает максимальное количество извлекаемых данных равным 10. Чтобы изменить это, просмотрите оригинальную документацию Strapi.

Создание задачи

Прежде чем мы сможем отправить запрос в Strapi на добавление задачи, нам нужно сделать следующее:

  • Нажмите Content-Type Builder на боковой панели навигации и кнопку Изменить.
  • Нажмите ДОПОЛНИТЕЛЬНЫЕ НАСТРОЙКИ, снимите флажок Черновик и публикация и нажмите Готово. › Strapi имеет настройку по умолчанию, которая позволяет администраторам просматривать каждый отправленный контент, предоставляя им возможность просматривать и оценивать его.
  • Затем нажмите значок «Изменить», чтобы отредактировать todoText.
  • Нажмите ДОПОЛНИТЕЛЬНЫЕ НАСТРОЙКИ, отметьте Обязательное поле, нажмите кнопку Готово и нажмите кнопку Сохранить в правом верхнем углу. .

Как только это будет сделано, мы сможем создать задачу. Откройте файл schema.ts и добавьте схему для добавления задачи.

// src/query/schema.ts
import { gql } from "@apollo/client";

//The rest of the code

export const ADDMUT = gql`
  mutation createTodo($todoText: String) {
    createTodo(data: { todoText: $todoText }) {
      data {
        id
        attributes {
          todoText
          createdAt
        }
      }
    }
  }
`;

Чтобы добавить задачу, мы импортируем схему ADDQUERY из schema.ts и функцию useMutation из apollo/client.

// src/app/page.tsx

//The rest of the code

import { useMutation } from "@apollo/client";
import { GETQUERY, ADDMUT } from "@/query/schema";

export default function Home() {
  const [todos, setTodos] = useState<[]>([]);
  const [createTodo] = useMutation(ADDMUT);
  const { loading, error, data } = useQuery(GETQUERY, {
    fetchPolicy: "no-cache",
  }); //Fetching all todos
  useEffect(() => {
    console.log(data?.todos?.data);
    setTodos(data?.todos?.data); //Storing all the todos
  }, [data]);
  const addTodo = async (todoText: string) => {
    await createTodo({
      //Creating a new todo
      variables: {
        todoText: todoText, //Passing the todo text
      },
    }).then(({ data }: any) => {
      setTodos([...todos, data?.createTodo?.data] as any); //Adding the new todo to the list
    });
  };

  //The rest of the code.
}

Редактирование задачи

Чтобы обновить данные в Strapi с помощью Graphql, мы будем использовать id конкретной задачи, которую мы обновляем. Откройте файл schema.ts и добавьте мутацию Graphql для функции обновления.

// src/query/schema.ts
import { gql } from "@apollo/client";

//The rest of the code

export const UPDATEMUT = gql`
  mutation updateTodo($id: ID!, $todoText: String!) {
    updateTodo(id: $id, data: { todoText: $todoText }) {
      data {
        id
        attributes {
          todoText
          createdAt
        }
      }
    }
  }
`;

Теперь импортируйте схему UPDATEMUT в файл pages.tsx.

// src/app/page.tsx
//The rest of the code

import { GETQUERY, ADDMUT, UPDATEMUT } from "@/query/schema";
export default function Home() {
  const [todos, setTodos] = useState<[]>([]);
  const [createTodo] = useMutation(ADDMUT);
  const [updateTodo] = useMutation(UPDATEMUT);

  //The rest of the code

  const editTodoItem = async (todo: any) => {
    const newTodoText = prompt("Enter new todo text or description:");
    if (newTodoText != null) {
      await updateTodo({
        //updating the todo
        variables: {
          id: todo.id,
          todoText: newTodoText,
        },
      }).then(({ data }: any) => {
        const moddedTodos: any = todos.map((_todo: any) => {
          if (_todo.id === todo.id) {
            return data?.updateTodo?.data;
          } else {
            return _todo;
          }
        });
        setTodos(moddedTodos);
      });
    }
  };

  //The rest of the code
}

Функция editTodoItem редактирует задачу. Он предлагает пользователю ввести новый текст задачи. После нажатия кнопки «ОК» в диалоговом окне подсказки задача редактируется с помощью задачи id.

Удаление задачи

Мы подошли к последнему разделу нашего CRUD-запроса. В этом разделе мы удалим задачу, используя идентификатор задачи. Откройте файл schema.ts и добавьте DELETEMUT.

// src/query/schema.ts
import { gql } from "@apollo/client";

//The rest of the code

export const DELETEMUT = gql`
  mutation deleteTodo($id: ID!) {
    deleteTodo(id: $id) {
      data {
        id
        attributes {
          todoText
          createdAt
        }
      }
    }
  }
`;

Импортируйте схему DELETEMUT в pages.tsx.

// src/app/page.tsx
//The rest of the code

import { GETQUERY, ADDMUT, UPDATEMUT, DELETEMUT } from "@/query/schema";
export default function Home() {
  const [todos, setTodos] = useState<[]>([]);
  const [createTodo] = useMutation(ADDMUT);
  const [updateTodo] = useMutation(UPDATEMUT);
  const [deleteMUT] = useMutation(DELETEMUT);

  //The rest of the code
  const deleteTodoItem = async (todo: any) => {
    if (confirm("Do you really want to delete this item?")) {
      await deleteMUT({
        //Deleting the todo
        variables: {
          id: todo.id,
        },
      }).then(({ data }: any) => {
        const newTodos = todos.filter((_todo: any) => _todo.id !== todo.id);
        setTodos(newTodos as any);
      });
    }
  };
  //The rest of the code
}

Получите полный исходный код из раздела ресурсов.

Функция deleteTodoItem принимает объект задачи для удаления в аргументе todo. Сначала он подтверждает, хочет ли пользователь удалить задачу, и если да, он приступает к удалению задачи. Это приведет к тому, что Strapi удалит задачу с идентификатором в своей базе данных. Затем мы отфильтровываем удаленные задачи и устанавливаем отфильтрованный результат в качестве новых задач в состоянии задач.

Ресурсы

Исходный код приложения вы можете найти здесь:

Вы также можете прочитать больше о Strapi иgraphql, используя ссылки:

Заключение

Ура 🎉, мы подошли к концу этой статьи. В статье показано, как интегрировать Strapi в NextJS, создав приложение для создания дел. Не стесняйтесь проверять приложение на разных компьютерах и комментировать любые ошибки, если они возникнут.