简体   繁体   中英

Redux-Form and React-RTE - Save RTE editorValue to form state?

I'm brand new to React/Redux and the works, so please excuse any naive assumptions/questions here...

I've managed to make a good amount of progress in the onboarding flow I'm building for my app thanks to the documentation for redux-form - it's a fantastic library!

However, I'm now running into a few issues because I'm trying to pass an instance of React-RTE ( https://github.com/sstur/react-rte ) as a custom Field component. I've been following the documentation here . So far I've been able to render the RTE and log the editorValue prop to the console, but I can't for the life of me get the form value to save to the form state. I asked posted this question as an issue on the redux-form gitrepo, but it probably makes sense to post here as well, as others may be having issues with custom Field Components. Any help would be much appreciated!

Here's the code I've been experimenting with:

My Form container (RoleForm.jsx) - snippet in question is JDEditor:

import React, {Component, PropTypes} from 'react';
import { connect } from 'react-redux'
import { Field, reduxForm, formValueSelector } from 'redux-form'
import validate from './validate.jsx'
import renderField from './renderField.jsx'
import JDEditor from './JDEditor.jsx'

const renderError = ({ meta: { touched, error } }) => touched && error ?
  <span>{error}</span> : false

class RoleForm extends React.Component {
   constructor(props) {
        super(props);
    }

    handleChange(editorValue){
      console.log("CHANGE | EditorValue: " + editorValue)
    }

    handleBlur(editorValue){
      console.log("BLUR | EditorValue: " + editorValue)
    }

     handleFocus(editorValue){
      console.log("FOCUS | EditorValue: " + editorValue)
    }

   render(){
    let { handleSubmit, previousPage, company, value} = this.props

    return (
      <div className="login-wrapper">
      <div className="form" style={{borderRadius:4, margin:'0 auto', padding:24, maxWidth:780}}>
      <h3 style={{fontWeight:700}}>Role Details</h3>
      <p>Here's what we were able to pull:</p>
      <form onSubmit={handleSubmit}>
          <div style={{width:'50%', display:'inline-block'}}><Field name="role" type="text" component={renderField} label="Role"/></div>
          <div style={{width:'50%', display:'inline-block'}}><Field name="role_url" type="url" component={renderField} label="Role Link"/></div>
          <div style={{width:'85%', display:'inline-block', borderBottom:'1px solid'}}></div>
          <label style={{display:'block', textAlign:'left', paddingLeft:'8px'}}>Role Description</label>
          <div style={{display:'inline-block', width:'100%', padding:'0px 8px 8px 8px'}}>
          <Field name="role_description" 
            component={props=><JDEditor format={'html'} value={{rte_value:props.editorValue}} onFocus={this.handleFocus.bind(this)} onBlur={this.handleBlur.bind(this)} onChange={this.handleChange.bind(this)} {...props} />} />
          </div>
        <div style={{marginTop:'10px', clear:'both'}}>
          <button type="button" className="btn btn-default" style={{width:'100px', marginRight:'4px'}} onClick={previousPage}>Back</button>
          <button type="submit" className="btn btn-primary" style={{width:'100px'}}>Continue</button>
        </div>
      </form>
      </div>
      <div style={{padding:'100%', background:'#f7f7f7'}}>
      </div>
      </div>
    )
  }
}

export default RoleForm = reduxForm({
  form: 'onboarding',
  destroyOnUnmount: false,
  validate
})(RoleForm)

And the JDEditor class:

import React, {Component} from 'react';
import RichTextEditor, {createEmptyValue} from 'react-rte';
import autobind from 'class-autobind';

import type {EditorValue} from 'react-rte';

type Props = {
  value: string;
  format: string;
  onChange: (value: string) => any;
};
type State = {
  editorValue: EditorValue;
};

export default class JDEditor extends Component {
  props: Props;
  state: State;
  // The [format, value] of what's currently displayed in the     <RichTextEditor />
  _currentValue: ?[string, string];

  constructor() {
    super(...arguments);
    autobind(this);
    this.state = {
      editorValue: createEmptyValue(),
    };
  }

  componentWillMount() {
    this._updateStateFromProps(this.props);
  }

  componentWillReceiveProps(newProps: Props) {
    this._updateStateFromProps(newProps);
  }

  _updateStateFromProps(newProps: Props) {
    let {value, format} = newProps;
    if (this._currentValue != null) {
      let [currentValue, currentFormat] = this._currentValue;
      if (format === currentFormat && value === currentValue) {
        return;
      }
    }
    let {editorValue} = this.state;
    this.setState({
      editorValue: editorValue.setContentFromString(value, format),
    });
    this._currentValue = [format, value];
  }

  render() {
    let {value, format, onChange, ...otherProps} = this.props; // eslint-disable-line no-unused-vars
    return (
      <RichTextEditor
        {...otherProps}
        value={this.state.editorValue}
        onChange={this._onChange}
      />
    );
  }

  _onChange(editorValue: EditorValue) {
    let {format, onChange} = this.props;
    let oldEditorValue = this.state.editorValue;
    this.setState({editorValue});
    let oldContentState = oldEditorValue ?     oldEditorValue.getEditorState().getCurrentContent() : null;
    let newContentState = editorValue.getEditorState().getCurrentContent();
    if (oldContentState !== newContentState) {
      let stringValue = editorValue.toString(format);
      // Optimization so if we receive new props we don't need
      // to parse anything unnecessarily.
      this._currentValue = [format, stringValue];
      if (onChange && stringValue !== this.props.value) {
        onChange(stringValue);
      }
    }
  } 
}

This is how I have done it. I wanted the content in markdown:

// in client side entry file
import RichTextEditor from 'react-rte'

window.RichTextEditor = RichTextEditor

And then the component is RichTextMarkdown.js .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM