This post was originally published on Medium. Link
The Need
I develop Shopify Apps as a Freelancer and Shopify has offered their own UI toolkit called Polaris which is highly recommended for building apps interfaces.
They offer React Components and also HTML/CSS version of components. Sadly, there is no Rich Text Editor component in the toolkit as of now. Although, it's under consideration.
Research
I did some research and found two options:
- TinyMCE
- Trix Editor
TinyMCE is feature rich and offers a lot, But I needed a simple one so I decided to go with Trix.
Getting Started:
Pull in Trix using npm:
npm install trix
Next, let's create a component named wysiwyg.jsx
and use it in App
component.
App.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import {
AppProvider,
Page,
Card,
Layout,
} from "@shopify/polaris";
import Wysiwyg from "./components/wysiwyg";
export default class App extends React.Component {
state = {
content: ""
}
render(){
return(
<AppProvider apiKey={apiKey} shopOrigin={shopOrigin} forceRedirect={true}>
<Page>
<Layout>
<Card>
<Wysiwyg />
</Card>
</Layout>
</Page>
</AppProvider>
);
}
}
wysiwyg.jsx
import React, { Component } from "react";
import Trix from "trix";
class Wysiwyg extends React.Component {
render() {
return (
<div>
<input
type="hidden"
id="trix"
/>
<trix-editor input="trix" />
</div>
);
}
}
export default Wysiwyg;
Trix editor stores its a content in a hidden element. ID property on that hidden element and input property on trix-editor
must be same.
At this point you will see Trix working, if styles are not there, you can pull the stylesheet from CDN, or put a link tag. I am using laravel-mix
so I imported the stylesheet in my app.scss
like below:
@import "~trix/dist/trix.css";
Populating the stored content 😍
We can pass the data to component with props.
<Wysiwyg value={this.state.content} />
and accepting this prop in the component as below:
<input type="hidden" id="trix" value={this.props.value} />
Updating the STATE 🤔
This is a little bit tricky. State is in the parent component and we need to tell the parent component that content of the editor is being changed.
Trix editor raises an event called trix-change
🔗 . We can listen to this event and raise our own custom event.
Since trix-editor
is in the DOM, we need refs to access it.
wysiwyg.jsx
import React, { Component } from "react";
import Trix from "trix";
class Wysiwyg extends React.Component {
constructor(props) {
super(props);
this.trixInput = React.createRef();
}
componentDidMount() {
this.trixInput.current.addEventListener("trix-change", event => {
console.log("trix change event fired");
this.props.onChange(event.target.innerHTML); //calling custom event
});
}
render() {
return (
<div>
<input type="hidden" id="trix" value={this.props.value} />
<trix-editor input="trix" ref={this.trixInput} />
</div>
);
}
}
export default Wysiwyg;
Event handler on the parent component, via props as below:
App.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import {
AppProvider,
Page,
Card,
Layout,
} from "@shopify/polaris";
import Wysiwyg from "./components/wysiwyg";
export default class App extends React.Component {
state = {
content: ""
}
render(){
return(
<AppProvider apiKey={apiKey} shopOrigin={shopOrigin} forceRedirect={true}>
<Page>
<Layout>
<Card>
<Wysiwyg onChange={this.handleContentChange} />
</Card>
</Layout>
</Page>
</AppProvider>
);
}
handleContentChange = (content) => {
this.setState({content : content});
};
}
If you need multiple wysiwyg
on same page, you can play around with passing props for id etc.
So, this is how you can use Trix Rich Text Editor in React and make it a reusable component.
This approach is heavily inspired by Laracast’s episode on Wysiwyg. here.
Happy coding 👨🏽💻
Top comments (0)