React-ace: Problem with ace inside Field component of Redux-Form

Created on 18 Dec 2017  路  6Comments  路  Source: securingsincity/react-ace

I have a similar issue to https://github.com/securingsincity/react-ace/issues/120 right now.

I am using react-ace inside redux-form, as a component passed to Field.
Anytime the code editor loses focus, the value is set to "" and two dots are displayed inside the ace editor.

My code is just like jschlieber in the original issue proposed, take a look:

import React from 'react'
import AceEditor from 'react-ace'
import _ from 'lodash';

import 'brace/mode/javascript';
import 'brace/theme/monokai';

export default function ReduxAce (props) {
    console.log(props.input.onBlur, props);

    const {
        input,
        theme = 'monokai',
        mode = 'javascript',
        fontSize = 14,
        tabSize = 2,
        width = '1000px',
        height = '500px',
        ...custom
    } = props;

    return (
        <AceEditor
            theme={theme}
            mode={mode}
            fontSize={fontSize}
            tabSize={tabSize}
            width={width}
            height={height}
            onBlur={() => props.input.onBlur(props.input.value)}
            editorProps={{$blockScrolling: Infinity}}
            {...input}
            {...custom}
        />
    )
}

and

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { saveDraft } from '../actions/index';
import { bindActionCreators } from 'redux';
import { Field, reduxForm } from 'redux-form';
import ReduxAce from '../components/redux_ace'

const ID = 'id123', NAME = 'name123', SOME_CODE = 'code123';

function mapStateToProps({draft}) {
    return {
        draft
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        saveDraft
    }, dispatch)
}


class Draft extends Component {
    renderField(field) {
        return (
            <div className="form-group">
                <label>{field.label}</label>
                <input
                    className="form-control"
                    type="text"
                    {...field.input}
                />
            </div>
        )

    }

    onSubmit(values) {
        console.log('sub',values);

        this.props.saveDraft({
            id: values[ID],
            name: values[NAME],
            code: values[SOME_CODE]
        });
    }

    render() {
        const { handleSubmit } = this.props;

        return (
            <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
                <Field
                    label="Id"
                    name={ID}
                    component={this.renderField}
                />

                <Field
                    label="Name"
                    name={NAME}
                    component={this.renderField}
                />
                <Field
                    label="Lambda code"
                    name={SOME_CODE}
                    component={ReduxAce}
                />

                // if I put it here, then it suddenly works fine <ReduxAce/>
                <button type="submit" className="btn btn-primary"> Submit</button>
            </form>
        );
    }
}

export default reduxForm({
    validate,
    form: 'DraftForm' 
})(
    connect(mapStateToProps, mapDispatchToProps)(Draft)
)

just before the button I put a comment just now, // if I put it here, then it suddenly works fine <ReduxAce/> - so yes, if I put the Ace Editor as is not as a Field component, then its value is not deleted. How you can see, I tried to use the onBlur handler and preserve the value, but I couldn't.

Thanks for any hints!

awaiting response

Most helpful comment

const aceOnBlur = (onBlur) => (_event, editor?) => {
    const value = editor.getValue();
    onBlur(value);
};

...
return (
    <AceEditor
          className={className}
          mode='html'
          theme='monokai'
          enableBasicAutocompletion={true}
          showPrintMargin={false}
          tabSize={4}
          setOptions={options}
          width='1000px'
          name={input.name}
          onBlur={aceOnBlur(input.onBlur)}
          onChange={input.onChange}
          onFocus={input.onFocus}
          value={input.value}
    />
)

works fine for me

All 6 comments

I've got the same issue. I don't see the problem with version 5.1.1, but in 5.8.0 it's an issue. Will update if I can figure it out.

const aceOnBlur = (onBlur) => (_event, editor?) => {
    const value = editor.getValue();
    onBlur(value);
};

...
return (
    <AceEditor
          className={className}
          mode='html'
          theme='monokai'
          enableBasicAutocompletion={true}
          showPrintMargin={false}
          tabSize={4}
          setOptions={options}
          width='1000px'
          name={input.name}
          onBlur={aceOnBlur(input.onBlur)}
          onChange={input.onChange}
          onFocus={input.onFocus}
          value={input.value}
    />
)

works fine for me

@drewen @spoonscen - Do either of you have suggestions on this as you guys have used redux-form in the past?

@avalkowsky - does @JFFby's suggestion work? The onBlur in your example passes the current input value to reduxForm's onBlur resetting the input, but I don't believe that value is updated as you type. I believe it's passing the __original__ value back each time, not the new value you just typed into the editor; when working with the custom components, you have two states to work with: the redux-form store data and the actual values on the input.

@drewen I'll give you some details tomorrow!

@JFFby sorry, that it took so long, shame on me.

Your solution is working!

@drewen thanks, I missed that 馃憤

@taylordowns2000

I also downgraded react-ace to 5.1.1 and tried it without onBlur callback but it was not working.
Maybe I made some another mistake, however if I was a developer from the future who run into this issue, I would use JFFbys solution :)

Thank you all for help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Yuanye picture Yuanye  路  7Comments

viridia picture viridia  路  4Comments

dmavrin picture dmavrin  路  3Comments

anderoonies picture anderoonies  路  5Comments

ponelat picture ponelat  路  3Comments