رد فعل مكون React لـ Easymde (أكثر شوكة Simplemde الطازجة).
اثنين فقط من التبعيات ، رد فعل (نظير) و easymde (نظير).
بنيت بواسطة @rip21؟
easymde أو codemirror أو cursor لتكون قادرة على معالجة ذلك.جدول المحتويات المتولد مع تخفيض التكلفة TOC
>=16.8.2easymde الآن تبعية النظراء ، يرجى تثبيته يدويًاlabel Propoptions مذكرات لمنع إنشاء مثيلات جديدة على كل عرض وغيره من هذه الأخطاء (المزيد عن ذلك أدناه)ref Forwards ، بحيث يمكنك بسهولة الوصول إلى div Wrapper باستخدام ref Prop.@babel/runtime لم يعد مساعدو وقت التشغيل مضمرين ولكنهم مستوردون. npm install --save react-simplemde-editor easymde
ملاحظة: ربما تحتاج إلى تثبيت @babel/runtime ، حاول بدونه ، ولكن إذا لم يكن لديك أي مشكلات ، فلا ينبغي عليك ذلك.
استضافة العرض التوضيحي
أو لرؤيته محليًا:
git clone https://github.com/RIP21/react-simplemde-editor.git
cd react-simplemde-editor
yarn install
yarn demo
open browser at localhost:3000
عرض الرمز التجريبي لمزيد من الأمثلة.
جميع الأمثلة أدناه في TypeScript
الاستخدام غير المنضبط
import React from "react" ;
import SimpleMDE from "react-simplemde-editor" ;
import "easymde/dist/easymde.min.css" ;
< SimpleMDE /> ; export const ControlledUsage = ( ) => {
const [ value , setValue ] = useState ( "Initial value" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
return < SimpleMdeReact value = { value } onChange = { onChange } /> ;
} ; يمكنك تعيين API لخيارات SimplemDe التي تنقلها كدعامة options . إذا كنت تستخدم TypeScript ، فسيتم استنتاجها بواسطة برنامج التحويل البرمجي.
ملاحظة: إذا لم تحدد معرفًا مخصصًا ، فسيقوم تلقائيًا بإنشاء معرف لك.
لاحظ أنك تحتاج إلى useMemo لتخطيط options المذكرات حتى لا تتغير في كل render! سيؤثر ذلك على السلوك والأداء لأنه في كل عرض للوالد الذي يجعل SimpleMdeReact ستحصل على مثيل جديد للمحرر ، والذي تريد بالتأكيد تجنبه! أيضًا ، إذا قمت بتغيير options في كل تغيير value ، فسوف تفقد التركيز. لذلك ، ضع options const خارج المكون ، أو إذا كانت options يجب أن تكون محددة جزئيًا أو بالكامل من قبل props ، فتأكد من useMemo في حالة المكونات الوظيفية/السنانير ، أو حقل الفصل للمكونات القائمة على class . أكثر قليلاً على ذلك هنا: #164
export const UsingOptions = ( ) => {
const [ value , setValue ] = useState ( "Initial" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
const autofocusNoSpellcheckerOptions = useMemo ( ( ) => {
return {
autofocus : true ,
spellChecker : false ,
} as SimpleMDE . Options ;
} , [ ] ) ;
return (
< SimpleMdeReact
options = { autofocusNoSpellcheckerOptions }
value = { value }
onChange = { onChange }
/>
) ;
} ; يمكنك تضمين خرائط المفاتيح باستخدام دعامة extraKeys . اقرأ المزيد في Codemirror Extra Keys
export const UpdateableByHotKeys = ( ) => {
const extraKeys = useMemo < KeyMap > ( ( ) => {
return {
Up : function ( cm ) {
cm . replaceSelection ( " surprise. " ) ;
} ,
Down : function ( cm ) {
cm . replaceSelection ( " surprise again! " ) ;
} ,
} ;
} , [ ] ) ;
const [ value , setValue ] = useState ( "initial" ) ;
const onChange = ( value : string ) => setValue ( value ) ;
return (
< SimpleMdeReact value = { value } onChange = { onChange } extraKeys = { extraKeys } />
) ;
} ; import ReactDOMServer from "react-dom/server" ;
export const CustomPreview = ( ) => {
const customRendererOptions = useMemo ( ( ) => {
return {
previewRender ( ) {
return ReactDOMServer . renderToString (
< ReactMarkdown
source = { text }
renderers = { {
CodeBlock : CodeRenderer ,
Code : CodeRenderer ,
} }
/>
) ;
} ,
} as SimpleMDE . Options ;
} , [ ] ) ;
return (
< div >
< h4 > Custom preview </ h4 >
< SimpleMdeReact options = { customRendererOptions } />
</ div >
) ;
} ;انظر القائمة الكاملة للأحداث هنا
import { SimpleMdeReact } from "react-simplemde-editor" ;
import type { SimpleMdeToCodemirrorEvents } from "react-simplemde-editor" ;
export const CustomEventListeners = ( ) => {
const [ value , setValue ] = useState ( "Initial value" ) ;
const onChange = useCallback ( ( value : string ) => {
setValue ( value ) ;
} , [ ] ) ;
// Make sure to always `useMemo` all the `options` and `events` props to ensure best performance!
const events = useMemo ( ( ) => {
return {
focus : ( ) => console . log ( value ) ,
} as SimpleMdeToCodemirrorEvents ;
} , [ ] ) ;
return < SimpleMdeReact events = { events } value = { value } onChange = { onChange } /> ;
} ; export const Autosaving = ( ) => {
const delay = 1000 ;
const autosavedValue = localStorage . getItem ( `smde_demo` ) || "Initial value" ;
const anOptions = useMemo ( ( ) => {
return {
autosave : {
enabled : true ,
uniqueId : "demo" ,
delay ,
} ,
} ;
} , [ delay ] ) ;
return (
< SimpleMdeReact id = "demo" value = { autosavedValue } options = { anOptions } />
) ;
} ;easymde أو codemirror أو cursor لتكون قادرة على معالجة ذلك. export const GetDifferentInstances = ( ) => {
// simple mde
const [ simpleMdeInstance , setMdeInstance ] = useState < SimpleMDE | null > ( null ) ;
const getMdeInstanceCallback = useCallback ( ( simpleMde : SimpleMDE ) => {
setMdeInstance ( simpleMde ) ;
} , [ ] ) ;
useEffect ( ( ) => {
simpleMdeInstance &&
console . info ( "Hey I'm editor instance!" , simpleMdeInstance ) ;
} , [ simpleMdeInstance ] ) ;
// codemirror
const [ codemirrorInstance , setCodemirrorInstance ] = useState < Editor | null > (
null
) ;
const getCmInstanceCallback = useCallback ( ( editor : Editor ) => {
setCodemirrorInstance ( editor ) ;
} , [ ] ) ;
useEffect ( ( ) => {
codemirrorInstance &&
console . info ( "Hey I'm codemirror instance!" , codemirrorInstance ) ;
} , [ codemirrorInstance ] ) ;
// line and cursor
const [ lineAndCursor , setLineAndCursor ] = useState < Position | null > ( null ) ;
const getLineAndCursorCallback = useCallback ( ( position : Position ) => {
setLineAndCursor ( position ) ;
} , [ ] ) ;
useEffect ( ( ) => {
lineAndCursor &&
console . info ( "Hey I'm line and cursor info!" , lineAndCursor ) ;
} , [ lineAndCursor ] ) ;
return (
< div >
< h4 > Getting instance of Mde and codemirror and line and cursor info </ h4 >
< SimpleMdeReact
value = "Go to console to see stuff logged"
getMdeInstance = { getMdeInstanceCallback }
getCodemirrorInstance = { getCmInstanceCallback }
getLineAndCursor = { getLineAndCursorCallback }
/>
</ div >
) ;
} ;إليكم كيف تفعل ذلك. يتطلب عمل بعض قطع المستعرضات ، ولكن هذا مثال كامل.
import { act , render , screen } from "@testing-library/react" ;
import { useState } from "react" ;
import { SimpleMdeReact } from "react-simplemde-editor" ;
import userEvent from "@testing-library/user-event" ;
// @ts-ignore
Document . prototype . createRange = function ( ) {
return {
setEnd : function ( ) { } ,
setStart : function ( ) { } ,
getBoundingClientRect : function ( ) {
return { right : 0 } ;
} ,
getClientRects : function ( ) {
return {
length : 0 ,
left : 0 ,
right : 0 ,
} ;
} ,
} ;
} ;
const Editor = ( ) => {
const [ value , setValue ] = useState ( "" ) ;
return < SimpleMdeReact value = { value } onChange = { setValue } /> ;
} ;
describe ( "Renders" , ( ) => {
it ( "succesfully" , async ( ) => {
act ( ( ) => {
render ( < Editor /> ) ;
} ) ;
const editor = await screen . findByRole ( "textbox" ) ;
userEvent . type ( editor , "hello" ) ;
expect ( screen . getByText ( "hello" ) ) . toBeDefined ( ) ;
} ) ;
} ) ; export interface SimpleMDEReactProps
extends Omit < React . HTMLAttributes < HTMLDivElement > , "onChange" > {
id ?: string ;
onChange ?: ( value : string , changeObject ?: EditorChange ) => void ;
value ?: string ;
extraKeys ?: KeyMap ;
options ?: SimpleMDE . Options ;
events ?: SimpleMdeToCodemirrorEvents ;
getMdeInstance ?: GetMdeInstance ;
getCodemirrorInstance ?: GetCodemirrorInstance ;
getLineAndCursor ?: GetLineAndCursor ;
placeholder ?: string ;
textareaProps ?: Omit <
React . HTMLAttributes < HTMLTextAreaElement > ,
"id" | "style" | "placeholder"
> ;
} default - SimpleMderEact
SimpleMdeReact - مثل default ولكن اسمه
الأنواع:
SimpleMdeReactProps - الدعائم من المكون
DOMEvent - بعض الأحداث المستخدمة للحصول على أحداث مصدرة أدناه
CopyEvents - أحداث Codemirror فقط نسخ
GlobalEvents - بعض أحداث Codemirror العالمية الأخرى
DefaultEvent - وظيفة معالج الأحداث Codemirror الافتراضية
IndexEventsSignature - توقيع الفهرس الذي يتوقع سلسلة كمفتاح ويعيد DefaultEvent
SimpleMdeToCodemirrorEvents - الأحداث المصنوعة يدويًا (استنادًا إلى @types/[email protected] التي يستخدمها easymde داخليًا) + تم دمج جميع ما سبق معًا في رسم خرائط كامل بين أسماء الأحداث Codemirror والمعالجات الفعلية events الدعامة
GetMdeInstance - توقيع وظيفة رد الاتصال التي تسترد مثيل MDE
GetCodemirrorInstance - توقيع وظيفة رد الاتصال الذي يسترجع مثيل codemirror
GetLineAndCursor - توقيع وظيفة رد الاتصال الذي يسترجع معلومات الخط والمؤشر
simplemde نفسها. التغييرات المحتملة ، لذلك صدمت النسخة إلى V4.simplemde/dist/simplemde.min.css الآن سيكون easymde/dist/easymde.min.css initialValue واستبدالها بدعامة value ، مما يسمح بتغييرات مباشرة على القيمة التي سيتم إجراؤها بعد حوامل المكون.لم يكن لدى الإصدار 1.0 خيارات SimplemDe التي تم تكوينها جيدًا ، ويعكس هذا ReadMe التغييرات التي تم إجراؤها لتشمل خيارات أفضل. لا يزال هذا مشروعًا جديدًا جدًا. الاختبار والتعليقات و PRS موضع ترحيب وتقدير.