<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sameer Ali</title>
    <description>The latest articles on DEV Community by Sameer Ali (@sameer52718).</description>
    <link>https://dev.to/sameer52718</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1035877%2F8cdd8f63-bb8a-4b58-abb3-aa3dcc7f39b6.jpeg</url>
      <title>DEV Community: Sameer Ali</title>
      <link>https://dev.to/sameer52718</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sameer52718"/>
    <language>en</language>
    <item>
      <title>Introducing react-rte-light: A Lightweight Rich Text Editor for React</title>
      <dc:creator>Sameer Ali</dc:creator>
      <pubDate>Wed, 13 Aug 2025 11:23:21 +0000</pubDate>
      <link>https://dev.to/sameer52718/introducing-react-rte-light-a-lightweight-rich-text-editor-for-react-2c7h</link>
      <guid>https://dev.to/sameer52718/introducing-react-rte-light-a-lightweight-rich-text-editor-for-react-2c7h</guid>
      <description>&lt;p&gt;Are you looking for a lightweight, flexible, and modern rich text editor for your React applications? Look no further! I'm excited to share &lt;a href="https://www.npmjs.com/package/react-rte-light" rel="noopener noreferrer"&gt;&lt;strong&gt;react-rte-light&lt;/strong&gt;&lt;/a&gt;, a TypeScript-based rich text editor built with &lt;a href="https://draftjs.org/" rel="noopener noreferrer"&gt;Draft.js&lt;/a&gt;. It’s designed to work seamlessly with React 16.8 to 19, offering a minimal-dependency alternative to heavier editors like React Quill. Whether you're building a blog platform, a note-taking app, or a CMS, &lt;code&gt;react-rte-light&lt;/code&gt; has you covered with its powerful features and simple API.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through what makes &lt;code&gt;react-rte-light&lt;/code&gt; special, how to get started, and how you can customize it to fit your project’s needs. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why react-rte-light?
&lt;/h2&gt;

&lt;p&gt;There are plenty of rich text editors out there, so why choose &lt;code&gt;react-rte-light&lt;/code&gt;? Here’s what sets it apart:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight and Minimal Dependencies&lt;/strong&gt;: Built with Draft.js and &lt;code&gt;draft-convert&lt;/code&gt;, it avoids the bloat of heavier libraries like Quill, keeping your bundle size lean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Compatibility&lt;/strong&gt;: Works with React 16.8 to 19, making it versatile for both legacy and modern projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tree-Shakable Builds&lt;/strong&gt;: Supports ESM and CommonJS, optimized for tree-shaking to include only what you need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Support&lt;/strong&gt;: Full type definitions for type-safe development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable and Themed&lt;/strong&gt;: Tailor the toolbar and styling with built-in light/dark themes or custom CSS variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessible&lt;/strong&gt;: Includes ARIA roles and keyboard navigation for better accessibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlled and Uncontrolled Modes&lt;/strong&gt;: Flexible API for both controlled (&lt;code&gt;value&lt;/code&gt; + &lt;code&gt;onChange&lt;/code&gt;) and uncontrolled (&lt;code&gt;defaultValue&lt;/code&gt;) usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard Shortcuts&lt;/strong&gt;: Supports standard shortcuts like &lt;code&gt;Ctrl+B&lt;/code&gt; for bold and &lt;code&gt;Ctrl+I&lt;/code&gt; for italic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you need a simple WYSIWYG editor or a highly customized one, &lt;code&gt;react-rte-light&lt;/code&gt; is designed to be flexible and developer-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core Editing&lt;/strong&gt;: Bold, italic, underline, strike-through, headings (H1, H2), links, blockquotes, ordered/unordered lists, and code blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Toolbar&lt;/strong&gt;: Pick and choose which controls to include via props.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theming&lt;/strong&gt;: Built-in light and dark themes, plus custom theming with CSS variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: ARIA-compliant with keyboard navigation support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Footprint&lt;/strong&gt;: Only depends on Draft.js and &lt;code&gt;draft-convert&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Install the package via npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-rte-light &lt;span class="nt"&gt;--legacy-peer-deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Use &lt;code&gt;--legacy-peer-deps&lt;/code&gt; to handle peer dependency conflicts, especially with React 19 and Draft.js.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, import the styles in your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light/dist/index.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;p&gt;Here’s a simple example to get you started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Start typing..."&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This renders a fully functional editor with all toolbar options enabled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controlled Mode (React 19 or 17)
&lt;/h3&gt;

&lt;p&gt;The editor works the same in React 19 and React 17, thanks to its backward-compatible design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ControlledEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;Initial content&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Type your content..."&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Uncontrolled Mode
&lt;/h3&gt;

&lt;p&gt;For simpler use cases, you can use the uncontrolled mode with &lt;code&gt;defaultValue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UncontrolledEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;p&amp;gt;Default content&amp;lt;/p&amp;gt;"&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-rte-light&lt;/code&gt; is built for flexibility. Here are some ways to tailor it to your needs:&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Toolbar
&lt;/h3&gt;

&lt;p&gt;Limit the toolbar to specific controls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CustomToolbar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolbarOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;italic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unordered-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt; &lt;span class="na"&gt;toolbarOptions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toolbarOptions&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Theming
&lt;/h3&gt;

&lt;p&gt;Switch to the built-in dark theme or define a custom theme with CSS variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemedEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Built-in dark theme&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CustomThemedEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Custom theme&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--editor-bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f0f0f0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--editor-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#333&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--link-color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;customTheme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Read-Only Mode
&lt;/h3&gt;

&lt;p&gt;Display content without allowing edits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-rte-light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ReadOnlyEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RichTextEditor&lt;/span&gt;
      &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;p&amp;gt;This is read-only content.&amp;lt;/p&amp;gt;"&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  API Reference
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;RichTextEditor&lt;/code&gt; component accepts the following props:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RichTextEditorProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// HTML string for controlled mode&lt;/span&gt;
  &lt;span class="nl"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// HTML string for uncontrolled mode&lt;/span&gt;
  &lt;span class="nl"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Called with updated HTML content&lt;/span&gt;
  &lt;span class="nl"&gt;toolbarOptions&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ToolbarOption&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of toolbar buttons&lt;/span&gt;
  &lt;span class="nl"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Disables editing if true&lt;/span&gt;
  &lt;span class="nl"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;CustomTheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Theme selection&lt;/span&gt;
  &lt;span class="nl"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Placeholder text&lt;/span&gt;
  &lt;span class="nl"&gt;className&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Additional CSS class for the editor&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ToolbarOption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;italic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;underline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strikethrough&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blockquote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ordered-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unordered-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code-block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CustomTheme&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Supported Toolbar Options
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bold&lt;/code&gt; (&lt;code&gt;Ctrl+B&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;italic&lt;/code&gt; (&lt;code&gt;Ctrl+I&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;underline&lt;/code&gt; (&lt;code&gt;Ctrl+U&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strikethrough&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;header-one&lt;/code&gt; (H1)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;header-two&lt;/code&gt; (H2)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;blockquote&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ordered-list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unordered-list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;code-block&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;link&lt;/code&gt; (prompts for URL)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Draft.js?
&lt;/h2&gt;

&lt;p&gt;I chose Draft.js as the underlying editor engine because it’s lightweight, well-maintained, and provides a robust foundation for rich text editing. Unlike Quill, it avoids unnecessary DOM manipulations and integrates naturally with React’s component model. The &lt;code&gt;draft-convert&lt;/code&gt; library simplifies HTML conversion, making it easy to work with standard web formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out!
&lt;/h2&gt;

&lt;p&gt;You can find the package on npm and GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/react-rte-light" rel="noopener noreferrer"&gt;&lt;strong&gt;npm&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/sameer52718/react-rte-light" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To test it locally, clone the repo and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/sameer52718/react-rte-light.git
&lt;span class="nb"&gt;cd &lt;/span&gt;react-rte-light
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--legacy-peer-deps&lt;/span&gt;
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;I’d love for you to contribute to &lt;code&gt;react-rte-light&lt;/code&gt;! Here’s how to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork the repository on &lt;a href="https://github.com/sameer52718/react-rte-light" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a feature branch: &lt;code&gt;git checkout -b feature/your-feature&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Commit your changes: &lt;code&gt;git commit -m "Add your feature"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Push to the branch: &lt;code&gt;git push origin feature/your-feature&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open a pull request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please include tests for new features and follow the existing TypeScript and ESLint standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback
&lt;/h2&gt;

&lt;p&gt;Have ideas for new features or found a bug? Open an issue on &lt;a href="https://github.com/sameer52718/react-rte-light/issues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or reach out on &lt;a href="https://x.com/your-username" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;. Let’s make &lt;code&gt;react-rte-light&lt;/code&gt; even better together!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-rte-light&lt;/code&gt; is a modern, lightweight solution for rich text editing in React. Its simplicity, flexibility, and compatibility make it a great choice for developers building content-heavy applications. Give it a try in your next project and let me know what you think!&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;: #React #RichTextEditor #TypeScript #DraftJS #WebDevelopment #Frontend #NPM #UI #JavaScript #OpenSource&lt;/p&gt;

</description>
      <category>richtexteditor</category>
      <category>react</category>
      <category>typescript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Effortless Firestore Queries in React with React Query</title>
      <dc:creator>Sameer Ali</dc:creator>
      <pubDate>Fri, 11 Jul 2025 08:00:01 +0000</pubDate>
      <link>https://dev.to/sameer52718/effortless-firestore-queries-in-react-with-react-query-48d5</link>
      <guid>https://dev.to/sameer52718/effortless-firestore-queries-in-react-with-react-query-48d5</guid>
      <description>&lt;h1&gt;
  
  
  Effortless Firestore Queries in React with React Query
&lt;/h1&gt;

&lt;p&gt;If you're working with &lt;strong&gt;Firebase Firestore&lt;/strong&gt; and &lt;strong&gt;React&lt;/strong&gt;, you probably love the simplicity of Firebase — but not necessarily the mess of &lt;code&gt;onSnapshot&lt;/code&gt;, manual state management, or stale data.&lt;/p&gt;

&lt;p&gt;As someone building modern apps with the &lt;strong&gt;MERN&lt;/strong&gt; stack, I wanted a way to use &lt;strong&gt;Firestore like a boss&lt;/strong&gt; — with real-time updates, caching, and minimal boilerplate.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://www.npmjs.com/package/react-firestore-query" rel="noopener noreferrer"&gt;&lt;code&gt;react-firestore-query&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is &lt;code&gt;react-firestore-query&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-firestore-query&lt;/code&gt; is a simple, powerful React hook that connects &lt;strong&gt;Firestore queries&lt;/strong&gt; with &lt;strong&gt;React Query&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time sync via Firestore's &lt;code&gt;onSnapshot&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Automatic caching using React Query&lt;/li&gt;
&lt;li&gt;Suspense and SSR compatibility&lt;/li&gt;
&lt;li&gt;TypeScript support out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just pass in a Firestore query (like &lt;code&gt;query(collection(db, 'users'))&lt;/code&gt;), and it returns live, cached data — with error/loading states managed for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-firestore-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Not Use &lt;code&gt;react-firebase-hooks&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Good question!&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://github.com/csfrequency/react-firebase-hooks" rel="noopener noreferrer"&gt;&lt;code&gt;react-firebase-hooks&lt;/code&gt;&lt;/a&gt; is awesome, it doesn't integrate with &lt;strong&gt;React Query&lt;/strong&gt; — which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No unified cache&lt;/li&gt;
&lt;li&gt;No global devtools&lt;/li&gt;
&lt;li&gt;No offline-first support&lt;/li&gt;
&lt;li&gt;No custom stale times or retry logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With &lt;code&gt;react-firestore-query&lt;/code&gt;, you're combining Firebase's real-time power with &lt;strong&gt;React Query’s full ecosystem&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: Fetch Active Users in Real-Time
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFirestoreQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-firestore-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;where&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/firestore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./firebase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usersQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;==&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ActiveUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirestoreQuery&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;usersQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s that simple.&lt;/p&gt;

&lt;p&gt;No manual subscriptions. No &lt;code&gt;useEffect&lt;/code&gt;. No state juggling.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works (Under the Hood)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uses Firestore's &lt;code&gt;onSnapshot()&lt;/code&gt; for real-time data&lt;/li&gt;
&lt;li&gt;Wraps it in a React Query &lt;code&gt;useQuery()&lt;/code&gt; hook&lt;/li&gt;
&lt;li&gt;Cleans up listeners on unmount&lt;/li&gt;
&lt;li&gt;Automatically updates cache when data changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even pass &lt;code&gt;queryKey&lt;/code&gt; dependencies to manage separate cache buckets — just like in React Query.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docs &amp;amp; GitHub
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/sameer52718/react-firestore-query" rel="noopener noreferrer"&gt;https://github.com/sameer52718/react-firestore-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/react-firestore-query" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/react-firestore-query&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Out, Star It, Share It
&lt;/h2&gt;

&lt;p&gt;This package is still growing — and I’d love your feedback, issues, PRs, or just a star.&lt;/p&gt;

&lt;p&gt;If you're building with &lt;strong&gt;Firebase + React&lt;/strong&gt;, give &lt;code&gt;react-firestore-query&lt;/code&gt; a try.&lt;/p&gt;

&lt;p&gt;Let’s make Firestore a little more fun to work with.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;br&gt;
Follow me for more React + Firebase dev tips.&lt;/p&gt;

</description>
      <category>react</category>
      <category>firebase</category>
      <category>opensource</category>
      <category>reactquery</category>
    </item>
  </channel>
</rss>
