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
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}
/>
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:
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}
/>
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("");
}
};
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(/ /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:
How to hide keyboard or dismiss the 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>
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(/ /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! 👩🏻💻
Top comments (5)
When i run this code it showing this error:
Warning: Error: Exception in HostFunction: TypeError: expected dynamic type
array', but had type
string'help me to fix this
Hi, I have a doubt, Im getting a response from API like HTML so can i able to load HTML format in Rich Editor ?
Hello I have a problem like I want to show text what written in Rich editor as you are showing buts its in div tags ? How should I run away from it like I only want plain text to be shown as I write .
You can use HtmlView to render it. It will then show as a plain text.
thank you so much mint!