How to use react-native-rich-editor on React Native
Tags: reactnative, expo, wysiwyg, richtext
Published: 2022-01-23 07:22:26

This article will show you an example of how to implement a [react-native-rich-editor](https://github.com/wxik/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.

```javascript
yarn add react-native-pell-rich-editor
or
npm i react-native-pell-rich-editor
```

## 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.

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

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5483wtc284lltjx0ag9.png)

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

```javascript
<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}
/>
```
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:
```javascript
  const richTextHandle = (descriptionText) => {
    if (descriptionText) {
      setShowDescError(false);
      setDescHTML(descriptionText);
    } else {
      setShowDescError(true);
      setDescHTML("");
    }
  };
```

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:
```javascript
 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!
    }
  };
```

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


![Empty Content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5zyk139gtlhej81w7zk.png)

## How to hide keyboard or dismiss the keyboard


![Keyboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dp34vc9eg3ubwfuw8hvo.png)

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:

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

## The Complete Code
Here is the complete code on Github: _[link](https://github.com/mintpw/rich-text-react-native-example/blob/main/App.js)_

```javascript
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",
  },
});

```

Happy Coding! 👩🏻‍💻