I'm trying to learn how to use React-Final-Form (RFF in short).
I've learnt how to use <Field>
component but now I need to add a custom component to use a WYSIWYG editor which is NOT provided by RFF.
So, I've chosen react-draft-wysiwyg.
Ok, first here my form:
const FormComponent = () => {
const handleSubmitOnClick = () => ({
news_title,
news_subtitle,
editor_content,
image_url,
}) => {
const data = {
"user": {
news_title: news_title,
news_subtitle: news_subtitle,
editor_content: editor_content <- here the content from the WYSIWYG editor
image_url: image_url
}
}
// API call here ....
}
return (
<>
<h1>News Main Page</h1>
<Form
onSubmit={handleSubmitOnClick()}
>
{
({
handleSubmit,
values,
submitting,
}) => (
<form onSubmit={handleSubmit} data-testid="form">
<Field
name='news_title'
placeholder='News Title'
validate={required}
>
{({ input, meta, placeholder }) => (
<div className={meta.active ? 'active' : ''}>
<input {...input}
type='text'
placeholder={placeholder}
/>
</div>
)}
</Field>
<Field
name='news_subtitle'
placeholder='News SubTitle'
validate={required}
>
{({ input, meta, placeholder }) => (
<div className={meta.active ? 'active' : ''}>
<input {...input}
type='text'
placeholder={placeholder}
/>
</div>
)}
</Field>
<WYSIWYGEditor /> **** HERE THE ISSUE ****
<MyDropzone />
<button
type="submit"
className="signup-button"
disabled={submitting}
>
Continue
</button>
</form>
)}
</Form>
</>
)
}
export default FormComponent;
This is the Editor file:
import React, { useState } from 'react';
// Components
import { EditorState, convertToRaw } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import draftToHtml from 'draftjs-to-html';
// Hooks version of the Class below (done by me)
const WYSIWYGEditor = () => {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const onEditorStateChange = editorState => {
return setEditorState(editorState)
}
return (
<div className="editor">
<Editor
editorState={editorState}
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
onEditorStateChange={onEditorStateChange}
/>
{
console.log('editorState => ', draftToHtml(convertToRaw(editorState.getCurrentContent())))
}
</div>
)
}
export default WYSIWYGEditor
The <WYSIWYGEditor />
returns the correct value, no prob there, but I don't how to integrate this component to the RFF flow by using name='editor_content'
and when the form submit
button is clicked.
Any help is much appreciated.
Joe
OK, I found the solution myself by looking at the React-Final-Form website.
In order to use custom solution OR 3rd Party components with <Field>
inside your RFF form, you need to add the following:
// main component file with RFF form
....
<Field
name="editor_content"
component={WYSIWYGEditor}
/>
etc...
Please note: do not try to pass the component this way component={<WYSIWYGEditor />}
otherwise it returns an error about not allowed to pass an Object
DO NOT forget to import the component :)
The example above will pass input
and meta
to the custom component to collect the data and use it in the form, and this is how:
// WYSIWYGEditor file
const WYSIWYGEditor = ({ input, meta }) => {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const onEditorStateChange = editorState => {
setEditorState(editorState)
return input.onChange(draftToHtml(convertToRaw(editorState.getCurrentContent())))
etc....
}
You'll notice that, in the onEditorStateChange
function I have been able to use input
from the props, and by using the onChange
method I can pass back the returned value to the parent component (RFF form).
I hope this will help someone else. Happy coding!