web-dev-qa-db-ja.com

react.jsをzurbと一緒にNiceで再生させる方法は、モーダルフォームを明らかにします

Zurbrevealとformをreactコンポーネントに統合しようとしています。これまでのところ、次のコードはモーダル形式を適切に表示します。

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
  ...

フォームコンポーネントを親コンポーネントに直接レンダリングするだけで、すべてが機能します。誰か助けてもらえますか?

20
Voldy

要するに、あなたはこれを間違ってやっていて、これはnot reactのバグです。

反応コンポーネントのDOMノードを変更するプラグインを使用すると、何らかの形で問題が発生します。

代わりに、react自体と補完的なcssを使用して、モーダルダイアログに必要な方法でコンポーネントを配置する必要があります。

Reactのstaticsコンポーネントプロパティを使用して、renderComponentをラップするいくつかの関数を定義し、reactダイアログを表示または非表示にするためのすてきなクリーンな関数呼び出しを提供するコンポーネントを作成することをお勧めします。これは私が過去に使用したものの縮小例です。注意:jQueryを使用しますが、jQueryコードが必要ない場合は、jQをelementByIdなどへの標準のjsapi呼び出しに置き換えることができます。

_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()

ダイアログは常に、IDが「dialog-anchor」のbodyのすぐ下にある新しいdomノードにアタッチされます。ダイアログがすでに開いているときにダイアログを開くと、新しい小道具に基づいてdomが更新されます(または同じでない場合)。

もちろん、ダイアログの内容を小道具の引数として渡すことは特に役に立ちません。私は通常、コンテンツのマークダウン-> htmlを解析するか、代わりにURLを小道具として提供するときに、コンポーネント内のajaxリクエストを介してhtmlを取得するために以下を拡張します。

上記のコードがまさにあなたが探していたものではないことは知っていますが、dom-modifyingプラグインをreactで動作させる良い方法はないと思います。 reactコンポーネントのdom表現が静的であるとは決して想定できないため、サードパーティのプラグインで正常に操作することはできません。このようにreactを使用したい場合は、フレームワークを使用している理由を再評価する必要があると正直に思います。

そうは言っても、上記のコードは、すべての操作がコンポーネント内で行われるダイアログの優れた出発点だと思います。結局のところ、これがreactjsのすべてです。

注意:コードはメモリから非常に迅速に記述され、現在の形式では実際にはテストされていないため、マイナーな構文エラーなどが発生した場合は申し訳ありません。

12
Mike Driver

マイクがしたことを行う方法は次のとおりですが、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>
    );
  }
});
5
orourkedd