В этом руководстве будут рассмотрены шаги по отправке данных Draft.js на сервер с помощью запроса POST, а затем как получить и отобразить эти данные с помощью запроса GET.

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

Зависимости: react, axios, draft-js

Структура:

  • Компонент AddPost с редактором Draft.js → useSubmit() hook для обработки запроса POST.
  • Компонент PostGallery для отображения сообщений → usePosts() крючок для обработки получения сообщений.

Предварительные требования для настройки маршрутов GET и POST

Во-первых, убедитесь, что у вас есть установленный маршрут, который может принимать запросы POST. Я собираюсь отправлять заметки из Draft.js, поэтому мой маршрут называется /posts. Объяснение того, как настроить серверную часть, выходит за рамки этой статьи, но все схемы, маршруты и контроллеры находятся в репозитории.

Экспресс-пользователи: убедитесь, что у вас настроено промежуточное ПО для синтаксического анализа тела, прежде чем выполнять запросы POST:

app.use(express.json());
app.use(express.urlencoded({extended: true}));

Верхняя строка позволит вам отправлять объекты JSON в теле запроса, а нижняя строка позволит вам отправлять строки, массивы и вложенные объекты.

1. Данные POST Draft.js

Отправьте данные Draft.js на сервер с помощью POST-запроса

Я хочу опубликовать свои данные, когда нажимаю кнопку сохранения в моем интерфейсе React. Я собираюсь прикрепить к этой кнопке функцию, которая будет отправлять запрос POST. Я собираюсь сохранить его на Submit в его родительском компоненте.

import React from 'react';
import RichEditor from '../components/editor/RichEditor';
import Button from '../components/Button';
import useSubmit from '../hooks/useSubmit';
import useRichEditor from '../hooks/useRichEditor';
const Add = () => {
const {
  editorState,
  onNoteChange,
  clearEditor,
  mapKeyToEditorCommand,
  handleKeyCommand,
  toggleInlineStyle,
  toggleBlockType
 } = useRichEditor();
const { submitPage } = useSubmit();
const handleSubmit = async (e) => {
   e.preventDefault();
   const data = editorState.getCurrentContent();
   await submitPage(data);
};
return (
   <form handleSubmit={handleSubmit}>
      <RichEditor 
          editorState={editorState}
          onNoteChange={onNoteChange}
          clearEditor={clearEditor}
          mapKeyToEditorCommand={mapKeyToEditorCommand}
          handleKeyCommand={handleKeyCommand}
          toggleInlineStyle={toggleInlineStyle}
          toggleBlockType={toggleBlockType}
         />
        <Button kind="primary" type="submit" label="add"/>
   </form>
  );
}
export default Add;

При отправке мы вызываем e.preventDefault(), чтобы страница не обновлялась, а затем получаем весь текущий контент в редакторе с помощью editorState.getCurrentContent(). Затем мы вызываем функцию handleSubmit в настраиваемом хуке.

Теперь давайте напишем функцию, которую мы прикрепили к нашей кнопке сохранения, handleSave (). Это та часть, куда мы фактически отправляем наши данные. Я использую Axios для всех вызовов API. Axios - это библиотека для выполнения HTTP-запросов; This - хорошее руководство по его использованию с React.

import { useState } from 'react';
import axios from 'axios';
import { convertToRaw } from 'draft-js';
export default function useSubmit() {
const submitPage = async (data) => {
     const content = JSON.stringify(convertToRaw(data));
     
     return axios.post('/posts', {
        content
     }).catch(err => console.log(err));
   }
  return {
    submitPage
  }
}

Разобьем этот POST-запрос на части:

  1. Я вызываю встроенный метод Draft.js getCurrentContent() в editorState. Этот метод возвращает объект currentState, который содержит текст и все его стили.
  2. Я использую встроенный метод Draft.js convertToRaw(), который преобразует состояние содержимого в объект JS, содержащий блоки содержимого. Кроме того, я использую метод JSON.stringify(), который превращает объект JS в строку JSON. Теперь его можно сохранить как строку.
  3. Я настроил свой запрос на аксиомы. Их можно отформатировать несколькими способами; Я предпочитаю использовать этот объектный формат для запросов POST. Я указываю method, url и конечную точку, data и headers. Обратите внимание, что мой объект данных отформатирован следующим образом:
{ 
   content
}

Потому что он отражает настройку моего объекта данных в вызове API createNote () в Express:

res.status(201).json({
     status: 'success',
     data: {
        content: newNote
       }
    })

Они должны соответствовать, чтобы данные могли правильно маршрутизироваться!

Давайте получим данные для нашего POST-запроса. Я собираюсь войти в свой редактор Draft.js и написать несколько образцов данных для отправки:

Я собираюсь добавить немного форматирования к этой заметке, чтобы убедиться, что мое форматирование сохраняется, когда я отправляю эти данные, а затем ПОЛУЧАЮ их позже. Я собираюсь добавить жирный текст и маркированный список:

Когда заметка размещена, она также отображается в моей базе данных следующим образом:

content: {"blocks":
[
{"key":"4rh99","text":"It's very gray today. I ate cornflakes ","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},
{"key":"fdh6","text":"honey","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"13aee","text":"a banana","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"bb1p5","text":"and peanutbutter ","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8j2ad","text":"for breakfast. ","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"fjio6","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"eblll","text":"Valentine's day is this weekend. ","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":16,"style":"BOLD"}],"entityRanges":[],"data":{}}],"entityMap":{}}

Это карта блоков, которая очерчивает различные блоки содержимого, похожие на абзацы. Если вы прочитаете это, это немного покажет, как Draft.js стилизует и хранит данные.

2. ПОЛУЧИТЬ данные Draft.js

Отображение данных Draft.js во внешнем интерфейсе не так просто, как выборка данных и их сопоставление с компонентом. Но это не сложно.

Сначала мы извлекаем данные Draft.js из нашей базы данных, используя запрос GET и /posts route, который мы создали в нашем API ранее.

Это настраиваемая ловушка для ПОЛУЧЕНИЯ сообщений, которая будет использоваться с компонентом PostGallery для отображения сообщений.

›usePosts.js

import { useState } from 'react';
import axios from 'axios';
import { convertToRaw } from 'draft-js';
export default function usePosts() {
const [posts, setPosts] = useState(null);
const getPosts = async (page, add) => {
   return axios.get(`/posts/`)
       .then(res => {
           const { docs } = res.data.data;
           setPosts(docs);
      }).catch(err => console.log(err));
  }
return {
   posts,
   getPosts
  }
}

Этот запрос GET извлекает данные, хранящиеся на маршруте /posts, который представляет собой все примечания, и устанавливает для этих документов состояние posts. Но помните, что это содержимое хранится в объекте. В объекте содержимое представляет собой строку JSON, которая содержит блоки содержимого заметки.

В галерее сообщений содержимое должно быть соответствующим образом проанализировано. Мы собираемся отображать сообщения в объекте редактора Draft.js - таком же, который использовался для написания сообщения, но со свойством readOnly, установленным таким образом, чтобы отображаемое примечание нельзя было редактировать.

Использование редактора для отображения заметки помимо ее написания имеет несколько преимуществ:

  • Легче отображать все стили заметок.
  • Свойство readOnly можно переключить на false, если после отображения сообщение можно редактировать.

›PostGallery.js

import React, { useEffect } from 'react';
import { Editor, EditorState, convertFromRaw } from 'draft-js';
import usePosts from '../hooks/usePosts';
const PostGallery = () => {
const { posts, getPosts } = usePosts();
useEffect(() => { 
    getPosts(); 
}, []);
return(
   <div className="posts">
   {pages && pages.map(el => {
    const contentState = convertFromRaw(JSON.parse(el.content));
    const editorState = EditorState.createWithContent(contentState);
       return(
        <div style={{paddingTop:'3rem'}}>
          <Editor editorState={editorState} readOnly={true}
          />
       </div>
        )
     })}
  </div>
)
};
export default PostGallery; 

Этот компонент:

  • Вызов функции, которая выполняет запрос GET, в настраиваемой ловушке в ловушке useEffect.
  • Использованиеel.content для получения содержимого примечания из объекта примечания и JSON.parse для преобразования его обратно в объект из его строкового состояния. Затем applyconvertFromRaw, функция Draft.js, которая преобразует объект с блоками содержимого обратно в читаемый текст.
  • Инициализация редактора Draft.js и установка этого анализируемого содержимого в качестве начального состояния редактора редактора.
  • Установка редактора на readOnly, как обсуждалось, чтобы его нельзя было редактировать.

Он будет отображаться во внешнем интерфейсе как текстовый блок (нередактируемый) с сохраненным богатым стилем. Если вы сохраните другие атрибуты, такие как автор сообщения, дата создания и т. Д., Их можно легко изменить, чтобы они также отображались здесь.

Это все, что нужно для POSTing и GETing данных Draft.js.

Резюме

POST

  • Получите текущий контент из состояния редактора с помощью editorState.getCurrentContent() и сохраните его в переменной.
  • Преобразуйте текущее состояние в строку с помощью следующих методов: JSON.stringify(convertToRaw(data));

ПОЛУЧИТЬ

  • Отображение данных в редакторе Draft.js, установленном на readOnly
  • Получите сообщение с сервера, а затем преобразуйте его в читаемый контент с помощью этого.
    const contentState = convertFromRaw(JSON.parse(el.content));
    const editorState = EditorState.createWithContent(contentState);
  • Покажите это в редакторе следующим образом:
<Editor editorState={editorState} readOnly={true}