1. ホーム
  2. javascript

jQueryからReact.jsへ移行する方法とは?[閉鎖しました]

2023-10-18 22:54:16

質問

ここ数日、Reactについて読み漁っています。私は見ているもののほとんどを理解することができますが、私はそれを書く能力に完全に自信を持っていません。私は、jQueryと要素を互いに追加することによって、そのhtml生成のすべてを行う小さなWebアプリに取り組んできました。これをReactで再構築すると速くなると思うので、試してみたいと思っています。この JSFiddle は、私が取り組んでいるようなことの小さな例です。Reactでどう書きますか?

JSです。

function remove() {
    this.remove();
}

function timed_append_new_element() {
    setTimeout(function () {
        var added_content = $("<span />", {
            class: "added_content",
            text: "Click to close",
            click: remove
        });
        container.append(added_content);
    }, 3000);
}

function append_new_element() {
    var added_content = $("<span />", {
        class: "timed_added_content",
        text: "Click to close",
        click: remove
    });
    container.append(added_content);
}


var container = $("<div />", {
    class: "container"
});
var header = $("<span />", {
    class: "header",
    text: "jQuery to React.js Header"
});
var add_button = $("<button />", {
    class: "add_button",
    text: "Add Element",
    click: append_new_element
});
var timed_add_button = $("<button />", {
    class: "add_button",
    text: "Add Element in 3 seconds",
    click: timed_append_new_element
});
container.append(header);
container.append(add_button);
container.append(timed_add_button);
$("body").append(container);

どのように解決するのですか?

良いReactアプリケーションを構築するのに役立つかもしれない、心に留めておくべきいくつかの基本的な考え方があります。

UIはデータの関数であるべきです。

多くの jQuery スープスタイルのアプリケーションでは、アプリケーションのビジネス ロジック、アプリケーションのデータ、および UI インタラクション コードがすべて混在しています。このため、この種のアプリケーションはデバッグが困難であり、特に成長が困難です。Reactは、多くの最新のクライアントサイドアプリケーションフレームワークと同様に、UIはデータの単なる表現であるという考えを強制します。UI を変更したい場合は、データの一部を変更し、フレームワークが使用するどのようなバインディング システムでも UI を更新できるようにする必要があります。

Reactでは、各コンポーネントは(理想的には)2つのデータのピースの関数です。 プロパティ コンポーネントのインスタンスに渡される 状態 があります。同じプロパティ(または "props")と状態が与えられると、コンポーネントは同じようにレンダリングされるはずです。

これは、具体的な例がないため、少し抽象的な考えとなりますが、とりあえずはこのまま進めていきます。

DOMに触れない

Reactでは、他のデータバインドフレームワークよりもさらに、可能な限りDOMを直接操作しないようにする必要があります。React のパフォーマンスと複雑さの特徴の多くは、React が実際の DOM を操作するために、内部で異なるアルゴリズムを持つ仮想 DOM を使用しているからこそ可能なのです。DOMを操作するコンポーネントを作るときはいつでも、Reactの仮想DOM機能を使って同じ機能をよりイディオムに作ることができないか自問自答すべきです。

もちろん、時にはDOMにアクセスする必要があったり、Reactで再構築せずにjQueryプラグインを組み込んだりすることもあるでしょう。このようなとき、Reactは優れた コンポーネントライフサイクルフック を利用することで、Reactのパフォーマンスがあまり低下しないようにすることができます(または、場合によっては、コンポーネントが完全に壊れないようにすることもできます)。

DOM を操作しないことは、上記の "UI as a function of the data, " と密接に関係します。

データフローを反転させる

大規模なReactアプリケーションでは、どのサブコンポーネントがアプリケーションデータの特定の部分を管理しているかを追跡するのが困難な場合があります。このため、React チームはデータ操作のロジックを中央の場所に置くことを推奨しています。これを行う最も簡単な方法は、子コンポーネントにコールバックを渡すことです。また、Facebook で開発された Flux というアーキテクチャもあり、これには 独自のウェブサイト .

コンポーザブルコンポーネントの作成

多くの場合、状態のいくつかのピースまたはUIロジックのいくつかのピースを管理する大きなコンポーネントを書きたくなることがあります。可能であれば (そして無理のない範囲で)、大きなコンポーネントを、データまたは UI ロジックの単一のピースで動作する小さなコンポーネントに分割することを考慮すべきです。そうすることで、アプリケーションの拡張や移動がより簡単になります。

ミュータブルデータに注意

コンポーネントの状態を更新するのは this.setState への呼び出しによってのみ更新されるべきなので、ミュータブルデータに注意することは有用です。複数の関数(またはコンポーネント!)が同じtickでミュータブルオブジェクトを更新する可能性がある場合、これは二重に当てはまります。Reactは状態の変更をバッチ処理しようとするかもしれませんし、更新を失うかもしれません Eliseu Monarのコメントにもあるように、ミュータブルオブジェクトを変異させる前にクローンすることを検討してください。Reactには 不変性ヘルパー があり、それを利用することができます。

もうひとつの選択肢は、変更可能なデータ構造を直接状態に保持することを一切見合わせることです。前述のFluxパターンは、この考えに対する興味深い試みです。


というReactのサイトに素晴らしい記事があります。 Reactで考える という素晴らしい記事があり、アイデアやモックアップをどのようにReactアプリケーションに変換するかを説明しています。具体的な例として、あなたが提供したコードを見てみましょう。基本的に管理するデータは1つです。 container 要素の中に存在するコンテンツのリストです。UI に対するすべての変更は、そのデータに対する追加、削除、および変更によって表すことができます。

上記のような考え方を応用すると、最終的には以下のようなアプリケーションになるかもしれません。

/** @jsx React.DOM */

var Application = React.createClass({
  getInitialState: function() {
    return {
      content: []
    };
  },

  render: function() {
    return (
      <div className="container">
        <span className="header">jQuery to React.js Header</span>
        <button className="add_button"
                onClick={this.addContent}>Add Element</button>
        <button className="add_button"
                onClick={this.timedAddContent}>Add Element in 3 Seconds</button>
        {this.state.content.map(function(content) {
          return <ContentItem content={content} removeItem={this.removeItem} />;
        }.bind(this))}
      </div>
    );
  },

  addContent: function() {
    var newItem = {className: "added_content", text: "Click to close"},
        content = this.state.content,
        newContent = React.addons.update(content, {$push: [newItem]});
    this.setState({content: newContent});
  },

  timedAddContent: function() {
    setTimeout(function() {
      var newItem = {className: "timed_added_content", text: "Click to close"},
          content = this.state.content,
          newContent = React.addons.update(content, {$push: [newItem]});
      this.setState({content: newContent});
    }.bind(this), 3000);
  },

  removeItem: function(item) {
    var content = this.state.content,
        index = content.indexOf(item);
    if (index > -1) {
      var newContent = React.addons.update(content, {$splice: [[index, 1]]});
      this.setState({content: newContent});
    }
  }
});

var ContentItem = React.createClass({
  propTypes: {
    content: React.PropTypes.object.isRequired,
    removeItem: React.PropTypes.func.isRequired
  },

  render: function() {
    return <span className={this.props.content.className}
                 onClick={this.onRemove}>{this.props.content.text}</span>;
  },

  onRemove: function() {
    this.props.removeItem(this.props.content);
  }
});

React.renderComponent(<Application />, document.body);

このコードの実行は このJSFiddle : http://jsfiddle.net/BinaryMuse/D59yP/

このアプリケーションは2つのコンポーネントで構成されています: トップレベルのコンポーネントである Application という配列を (その状態で) 管理するものです。 content というコンポーネントと ContentItem というコンポーネントがあり、これはその配列から一つの項目のUIと動作を表します。 Application 's render メソッドは ContentItem 要素を返します。

の中の値を管理するためのロジックは、すべて content 配列内の値を管理するロジックはすべて Application コンポーネントで処理されます。 ContentItem コンポーネントは 参照 への Application 's removeItem というメソッドがありますが、これは ContentItem メソッドに委ねられます。これにより、状態を操作するためのすべてのロジックがトップレベルコンポーネントの内部に保持されます。