Use Kria Lite WYSIWYG Editor in React
Learn how to integrate the lightweight Kria Lite WYSIWYG editor into your React application. This guide covers installation, React hooks, TypeScript support, and best practices.
📋 Prerequisites
- ✓ React 16.8+ (for hooks support)
- ✓ Node.js and npm/yarn installed
- ✓ Basic understanding of React components
Installation
Install Kria Lite WYSIWYG editor using npm or yarn:
# Using npm
npm install kria-lite
# Using yarn
yarn add kria-lite
# Using pnpm
pnpm add kria-lite
The package includes both the JavaScript library and CSS styles. No additional dependencies required!
Basic Usage
Here's the simplest way to use Kria Lite in a React component:
import React, { useEffect, useRef } from 'react';
import { WYSIWYG } from 'kria-lite';
import 'kria-lite/dist/kria.editor.css';
function Editor() {
const editorRef = useRef(null);
const instanceRef = useRef(null);
useEffect(() => {
// Initialize the editor
if (editorRef.current && !instanceRef.current) {
instanceRef.current = WYSIWYG.init(editorRef.current, {
height: '300px',
placeholder: 'Start writing...'
});
}
// Cleanup on unmount
return () => {
if (instanceRef.current) {
instanceRef.current.destroy();
instanceRef.current = null;
}
};
}, []);
return (
<div>
<textarea ref={editorRef} />
</div>
);
}
export default Editor;
Custom React Hook
Create a reusable hook for better code organization:
// hooks/useKriaEditor.js
import { useEffect, useRef, useCallback } from 'react';
import { WYSIWYG } from 'kria-lite';
export function useKriaEditor(options = {}) {
const editorRef = useRef(null);
const instanceRef = useRef(null);
useEffect(() => {
if (editorRef.current && !instanceRef.current) {
instanceRef.current = WYSIWYG.init(editorRef.current, {
height: '300px',
...options
});
}
return () => {
if (instanceRef.current) {
instanceRef.current.destroy();
instanceRef.current = null;
}
};
}, []);
const getContent = useCallback(() => {
return instanceRef.current?.getContent() || '';
}, []);
const setContent = useCallback((html) => {
instanceRef.current?.setContent(html);
}, []);
const focus = useCallback(() => {
instanceRef.current?.focus();
}, []);
return {
editorRef,
getContent,
setContent,
focus,
instance: instanceRef
};
}
Use the hook in your components:
import { useKriaEditor } from './hooks/useKriaEditor';
function BlogEditor() {
const { editorRef, getContent, setContent } = useKriaEditor({
placeholder: 'Write your blog post...',
imageUploadUrl: '/api/upload'
});
const handleSave = () => {
const content = getContent();
console.log('Saving:', content);
// Save to your backend
};
return (
<div>
<textarea ref={editorRef} />
<button onClick={handleSave}>Save</button>
</div>
);
}
TypeScript Support
Kria Lite includes TypeScript definitions. Here's a typed version of the hook:
// hooks/useKriaEditor.ts
import { useEffect, useRef, useCallback } from 'react';
import { WYSIWYG, EditorOptions, EditorInstance } from 'kria-lite';
interface UseKriaEditorResult {
editorRef: React.RefObject<HTMLTextAreaElement>;
getContent: () => string;
setContent: (html: string) => void;
focus: () => void;
instance: React.RefObject<EditorInstance | null>;
}
export function useKriaEditor(
options: Partial<EditorOptions> = {}
): UseKriaEditorResult {
const editorRef = useRef<HTMLTextAreaElement>(null);
const instanceRef = useRef<EditorInstance | null>(null);
useEffect(() => {
if (editorRef.current && !instanceRef.current) {
instanceRef.current = WYSIWYG.init(editorRef.current, {
height: '300px',
...options
});
}
return () => {
instanceRef.current?.destroy();
instanceRef.current = null;
};
}, []);
const getContent = useCallback((): string => {
return instanceRef.current?.getContent() ?? '';
}, []);
const setContent = useCallback((html: string): void => {
instanceRef.current?.setContent(html);
}, []);
const focus = useCallback((): void => {
instanceRef.current?.focus();
}, []);
return { editorRef, getContent, setContent, focus, instance: instanceRef };
}
Controlled Component
Create a fully controlled WYSIWYG component with onChange support:
import React, { useEffect, useRef } from 'react';
import { WYSIWYG } from 'kria-lite';
interface RichEditorProps {
value: string;
onChange: (html: string) => void;
placeholder?: string;
height?: string;
}
export function RichEditor({
value,
onChange,
placeholder = 'Start writing...',
height = '300px'
}: RichEditorProps) {
const editorRef = useRef<HTMLTextAreaElement>(null);
const instanceRef = useRef<any>(null);
const isInternalChange = useRef(false);
useEffect(() => {
if (editorRef.current && !instanceRef.current) {
instanceRef.current = WYSIWYG.init(editorRef.current, {
height,
placeholder,
onChange: (content: string) => {
isInternalChange.current = true;
onChange(content);
isInternalChange.current = false;
}
});
// Set initial value
if (value) {
instanceRef.current.setContent(value);
}
}
return () => {
instanceRef.current?.destroy();
instanceRef.current = null;
};
}, []);
// Sync external value changes
useEffect(() => {
if (instanceRef.current && !isInternalChange.current) {
const currentContent = instanceRef.current.getContent();
if (currentContent !== value) {
instanceRef.current.setContent(value);
}
}
}, [value]);
return <textarea ref={editorRef} />;
}
Usage with React state:
function App() {
const [content, setContent] = useState('<p>Initial content</p>');
return (
<RichEditor
value={content}
onChange={setContent}
placeholder="Write something amazing..."
/>
);
}
Image Upload Configuration
Configure image uploads with your backend API:
const editor = WYSIWYG.init(editorRef.current, {
imageUploadUrl: '/api/upload',
imageUploadHeaders: {
'Authorization': `Bearer ${token}`
},
imageUploadParams: {
'folder': 'blog-images'
},
onImageUpload: (response) => {
// Return the image URL from your API response
return response.url;
},
onImageUploadError: (error) => {
console.error('Upload failed:', error);
alert('Failed to upload image');
}
});
Form Integration
Integrate with popular form libraries like React Hook Form:
import { Controller } from 'react-hook-form';
import { RichEditor } from './RichEditor';
function BlogForm({ control }) {
return (
<form>
<Controller
name="content"
control={control}
defaultValue=""
render={({ field }) => (
<RichEditor
value={field.value}
onChange={field.onChange}
placeholder="Write your post content..."
/>
)}
/>
</form>
);
}
Best Practices
✅ Do: Clean up on unmount
Always call destroy() when the
component unmounts to prevent memory leaks.
✅ Do: Lazy load for performance
Use React.lazy() to load the
editor only when needed, reducing initial bundle size.
❌ Don't: Re-initialize on every render
Store the editor instance in a ref and only initialize once. Multiple initializations will cause performance issues.
❌ Don't: Trust user HTML blindly
Even though Kria Lite has XSS protection, always sanitize HTML on the server before storing or displaying user-generated content.
Next Steps
You now have Kria Lite WYSIWYG editor running in your React application! Here are some resources to continue learning: