DEV Community

Mint
Mint

Posted on

How to use react-native-rich-editor on React Native

This article will show you an example of how to implement a react-native-rich-editor and its common problems. In this example, I'm working on Expo (in case you wonder if this library supported Expo or not ).

The most common problems

  • How to check for empty content
  • How to hide keyboard or dismiss the keyboard
  • Crashed on Android when using navigation

I will show you the solutions to these problems in this example.

Setup

Install react-native-pell-rich-editor alongside react-native-webview.

yarn add react-native-pell-rich-editor
or
npm i react-native-pell-rich-editor
Enter fullscreen mode Exit fullscreen mode

Example

On react-native-pell-rich-editor, they have two components which are the RichEditor and RichToolbar.

RichEditor

To receive a fully functional Rich text Editor, add this component in your view hierarchy.

 <RichEditor
   ref={richText} // from useRef()
   onChange={richTextHandle}
   placeholder="Write your cool content here :)"
   androidHardwareAccelerationDisabled={true}
   style={styles.richTextEditorStyle}
   initialHeight={250}
 />
Enter fullscreen mode Exit fullscreen mode

If your app on Android crashed when you navigated to another screen make sure that you use

androidHardwareAccelerationDisabled={true}

This is what it looks like:

RichEditor

RichToolbar

This is a Component that provides a toolbar. It is designed to be used together with a RichEditor component.

<RichToolbar
   editor={richText}
   selectedIconTint="#873c1e"
   iconTint="#312921"
   actions={[
     actions.insertImage,
     actions.setBold,
     actions.setItalic,
     actions.insertBulletsList,
     actions.insertOrderedList,
     actions.insertLink,
     actions.setStrikethrough,
     actions.setUnderline,
   ]}
   style={styles.richTextToolbarStyle}
/>
Enter fullscreen mode Exit fullscreen mode

Because RichToolbar component needs to ref to RichEditor component I recommend you to write RichEditor component above RichToolbar component and then you can style them by using flexDirection: "column-reverse" I will show you how to style them in the complete code

How to check for empty content

You might want to check for empty content before users submit their information, or what should we do if they only type whitespaces?

We will update 2 states in richTextHandle function, for showing them the error text and we will need the HTML content that we get from richEditor to check for empty content later.

richTextHandle function:

  const richTextHandle = (descriptionText) => {
    if (descriptionText) {
      setShowDescError(false);
      setDescHTML(descriptionText);
    } else {
      setShowDescError(true);
      setDescHTML("");
    }
  };
Enter fullscreen mode Exit fullscreen mode

We will replace HTML tags and whitespaces with the empty string and now we have only texts without any HTML tag so we can check if the length of the text is less than or equal to zero.

submitContentHandle function:

 const submitContentHandle = () => {
    const replaceHTML = descHTML.replace(/<(.|\n)*?>/g, "").trim();
    const replaceWhiteSpace = replaceHTML.replace(/&nbsp;/g, "").trim();

    if (replaceWhiteSpace.length <= 0) {
      setShowDescError(true);
    } else {
      // send data to your server!
    }
  };
Enter fullscreen mode Exit fullscreen mode

This is what it looks like when users submit an empty content:

Empty Content

How to hide keyboard or dismiss the keyboard

Keyboard

Because RichEditor is not general input you can't just press outside input to dismiss the keyboard. You need to write a function to dismiss the keyboard by yourself. In this case, I will write that function outside the RichText like this:

<Pressable onPress={() => richText.current?.dismissKeyboard()}>
 <Text style={styles.headerStyle}>Your awesome Content</Text>
   <View style={styles.htmlBoxStyle}>
     <Text>{descHTML}</Text>
   </View>
</Pressable>
Enter fullscreen mode Exit fullscreen mode

The Complete Code

Here is the complete code on Github: link

import { useRef, useState } from "react";
import {
  Pressable,
  SafeAreaView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";
import {
  actions,
  RichEditor,
  RichToolbar,
} from "react-native-pell-rich-editor";

export default function App() {
  const richText = useRef();

  const [descHTML, setDescHTML] = useState("");
  const [showDescError, setShowDescError] = useState(false);

  const richTextHandle = (descriptionText) => {
    if (descriptionText) {
      setShowDescError(false);
      setDescHTML(descriptionText);
    } else {
      setShowDescError(true);
      setDescHTML("");
    }
  };

  const submitContentHandle = () => {
    const replaceHTML = descHTML.replace(/<(.|\n)*?>/g, "").trim();
    const replaceWhiteSpace = replaceHTML.replace(/&nbsp;/g, "").trim();

    if (replaceWhiteSpace.length <= 0) {
      setShowDescError(true);
    } else {
      // send data to your server!
    }
  };

  return (
    <SafeAreaView edges={["bottom", "left", "right"]} style={{ flex: 1 }}>
      <View style={styles.container}>
        <Pressable onPress={() => richText.current?.dismissKeyboard()}>
          <Text style={styles.headerStyle}>Your awesome Content</Text>
          <View style={styles.htmlBoxStyle}>
            <Text>{descHTML}</Text>
          </View>
        </Pressable>
        <View style={styles.richTextContainer}>
          <RichEditor
            ref={richText}
            onChange={richTextHandle}
            placeholder="Write your cool content here :)"
            androidHardwareAccelerationDisabled={true}
            style={styles.richTextEditorStyle}
            initialHeight={250}
          />
          <RichToolbar
            editor={richText}
            selectedIconTint="#873c1e"
            iconTint="#312921"
            actions={[
              actions.insertImage,
              actions.setBold,
              actions.setItalic,
              actions.insertBulletsList,
              actions.insertOrderedList,
              actions.insertLink,
              actions.setStrikethrough,
              actions.setUnderline,
            ]}
            style={styles.richTextToolbarStyle}
          />
        </View>
        {showDescError && (
          <Text style={styles.errorTextStyle}>
            Your content shouldn't be empty πŸ€”
          </Text>
        )}

        <TouchableOpacity
          style={styles.saveButtonStyle}
          onPress={submitContentHandle}>
          <Text style={styles.textButtonStyle}>Save</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    height: "100%",
    backgroundColor: "#ccaf9b",
    padding: 20,
    alignItems: "center",
  },

  headerStyle: {
    fontSize: 20,
    fontWeight: "600",
    color: "#312921",
    marginBottom: 10,
  },

  htmlBoxStyle: {
    height: 200,
    width: 330,
    backgroundColor: "#fff",
    borderRadius: 10,
    padding: 20,
    marginBottom: 10,
  },

  richTextContainer: {
    display: "flex",
    flexDirection: "column-reverse",
    width: "100%",
    marginBottom: 10,
  },

  richTextEditorStyle: {
    borderBottomLeftRadius: 10,
    borderBottomRightRadius: 10,
    borderWidth: 1,
    borderColor: "#ccaf9b",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.23,
    shadowRadius: 2.62,
    elevation: 4,
    fontSize: 20,
  },

  richTextToolbarStyle: {
    backgroundColor: "#c6c3b3",
    borderColor: "#c6c3b3",
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    borderWidth: 1,
  },

  errorTextStyle: {
    color: "#FF0000",
    marginBottom: 10,
  },

  saveButtonStyle: {
    backgroundColor: "#c6c3b3",
    borderWidth: 1,
    borderColor: "#c6c3b3",
    borderRadius: 10,
    padding: 10,
    width: "25%",
    alignItems: "center",
    justifyContent: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.23,
    shadowRadius: 2.62,
    elevation: 4,
    fontSize: 20,
  },

  textButtonStyle: {
    fontSize: 18,
    fontWeight: "600",
    color: "#312921",
  },
});

Enter fullscreen mode Exit fullscreen mode

Happy Coding! πŸ‘©πŸ»β€πŸ’»

Discussion (0)