Как заставить играть в response.js вместе с zurb, показать модальную форму

Я пытаюсь интегрировать zurb раскрыть с формой в компонент реагировать. Пока следующий код правильно отображает модальную форму:

ModalForm = React.createClass({
  handleSubmit: function(attrs) {
    this.props.onSubmit(attrs);
    return false;
  },

  render: function(){
    return(
      <div>
        <a href="#" data-reveal-id="formModal" className="button">Add new</a>
        <div id="formModal" className="reveal-modal" data-reveal>
          <h4>Add something new</h4>
          <Form onSubmit={this.handleSubmit} />
          <a className="close-reveal-modal">&#215;</a>
        </div>
      </div>
    );
  }
});

Form компонент довольно стандартный:

Form = React.createClass({
  handleSubmit: function() {
    var body = this.refs.body.getDOMNode().value.trim();
    if (!body) {
      return false;
    }
    this.props.onSubmit({body: body});
    this.refs.body.getDOMNode().value = '';
    return false;
  },
  render: function(){
    return(
      <form onSubmit={this.handleSubmit}>
        <textarea name="body" placeholder="Say something..." ref="body" />
        <input type="submit" value="Send" className="button" />
      </form>
    );
  }
}); 

Проблема: когда я рендерил компонент формы внутри модального компонента формы и вводил что-то в форму ввода, я вижу в консоли исключение Uncaught object, Это стек:

Uncaught object
  invariant
  ReactMount.findComponentRoot
  ReactMount.findReactNodeByID
  getNode
  ...

Если я просто визуализирую компонент формы непосредственно в родительском компоненте, тогда все работает. Кто-нибудь может помочь, пожалуйста?

2 ответа

Решение

Короче говоря, вы делаете это неправильно, и это не ошибка в реакции.

Если вы используете какой-либо плагин, который изменяет dom-узлы реагирующего компонента, то он так или иначе сломает вещи.

Вместо этого вам следует использовать саму реакцию и дополнительный css, чтобы расположить компонент так, как вы хотите для своего модального диалога.

Я хотел бы предложить создать компонент, который использует реагирует statics свойство компонента для определения пары функций renderComponent чтобы дать вам хороший чистый вызов функции, чтобы показать или скрыть диалог реакции. Вот урезанный пример того, что я использовал в прошлом. NB: он использует jQuery, но вы можете заменить jQ стандартными вызовами js api на такие вещи, как elementById и т. д., если вы не хотите код JQuery.

window.MyDialog = React.createClass({
    propTypes: {
        title:      React.PropTypes.string.isRequired,
        content:    React.PropTypes.string.isRequired
    },
    statics: {

        // open a dialog with props object as props
        open: function(props) {
            var $anchor = $('#dialog-anchor');
            if (!$anchor.length) {
                $anchor = $('<div></div>')
                    .prop('id', 'dialog-anchor');
                    .appendTo('body');
            }
            return React.renderComponent(
                MyDialog(props),
                $anchor.get(0)
            );
        },

        // close a dialog
        close: function() {
            React.unmountComponentAtNode($('#dialog-anchor').get(0));
        }
    },

    // when dialog opens, add a keyup event handler to body
    componentDidMount: function() {
        $('body').on('keyup.myDialog', this.globalKeyupHandler);
    },

    // when dialog closes, clean up the bound keyup event handler on body 
    componentWillUnmount: function() {
        $('body').off('keyup.myDialog');
    },

    // handles keyup events on body
    globalKeyupHandler: function(e) {
        if (e.keyCode == 27) { // ESC key

            // close the dialog
            this.statics.close();
        }
    },

    // Extremely basic dialog dom layout - use your own
    render: function() {
        <div className="dialog">
            <div className="title-bar">
                <div className="title">{this.props.title}</div>
                    <a href="#" className="close" onClick={this.closeHandler}>
                </div>
            </div>
            <div className="content">
                {this.props.content}
            </div>
        </div>
    }
});

Затем вы открываете диалог, вызывая:

MyDialog.open({title: 'Dialog Title', content: 'My dialog content'});

И закройте его

MyDialog.close()

Диалог всегда присоединяется к новому узлу dom непосредственно под телом с идентификатором 'dialog-anchor'. Если вы откроете диалоговое окно, когда оно уже открыто, оно просто обновит домен на основе новых реквизитов (или нет, если они одинаковые).

Конечно, передача содержимого диалога в качестве аргумента поддержки не особенно полезна. Я обычно расширяю ниже, чтобы либо разобрать markdown -> html для содержимого, либо получить html через ajax-запрос внутри компонента, если вместо этого указывать url в качестве prop.

Я знаю, что приведенный выше код не совсем то, что вы искали, но я не думаю, что есть хороший способ заставить dom-модифицирующий плагин работать с реагировать. Вы никогда не можете предположить, что представление dom компонента реакции является статическим, и, следовательно, оно не может успешно управляться сторонним плагином. Я искренне думаю, что если вы хотите использовать реакцию таким образом, вам следует пересмотреть, почему вы используете фреймворк.

Тем не менее, я думаю, что приведенный выше код является отличной отправной точкой для диалога, в котором все манипуляции происходят внутри компонента, что, в конечном счете, является тем, что все-таки в действительности представляет собой ijj!

Примечание: код был написан очень быстро из памяти и фактически не тестировался в текущей форме, поэтому извините, если есть какие-то незначительные синтаксические ошибки или что-то еще.

Вот как сделать то же самое, что и Майк, но используя модальное сообщение zf:

var Dialog = React.createClass({
  statics: {
    open: function(){
      this.$dialog = $('#my-dialog');

      if (!this.$dialog.length) {
        this.$dialog = $('<div id="my-dialog" class="reveal-modal" data-reveal role="dialog"></div>')
          .appendTo('body');
      }

      this.$dialog.foundation('reveal', 'open');

      return React.render(
        <Dialog close={this.close.bind(this)}/>,
        this.$dialog[0]
      );
    },
    close: function(){
      if(!this.$dialog || !this.$dialog.length) {
        return;
      }

      React.unmountComponentAtNode(this.$dialog[0]);
      this.$dialog.foundation('reveal', 'close');
    },
  },
  render : function() {
    return (
      <div>
        <h1>This gets rendered into the modal</h1>
        <a href="#" className="button" onClick={this.props.close}>Close</a>
      </div>
    );
  }
});
Другие вопросы по тегам