サーチ…


備考

React.createClass React.createClass で廃止され、v16削除される予定です。依然として必要なもののためのドロップイン交換パッケージがあります。それを使用する例を更新する必要があります。

基本コンポーネント

与えられたHTMLファイル:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel" src="scripts/example.js"></script>
  </body>
</html>

別のファイルに次のコードを使用して、基本コンポーネントを作成することができます。

scripts / example.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class FirstComponent extends Component {
  render() {
    return (
      <div className="firstComponent">
        Hello, world! I am a FirstComponent.
      </div>
    );
  }
}
ReactDOM.render(
  <FirstComponent />, // Note that this is the same as the variable you stored above
  document.getElementById('content')
);

次の結果が得られます( div#content内にあるものに注意してください)。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
  </head>
  <body>
    <div id="content">
        <div className="firstComponent">
            Hello, world! I am a FirstComponent.
        </div>
    </div>
    <script type="text/babel" src="scripts/example.js"></script>
  </body>
</html>

ネスティングコンポーネント

ReactJSの力の多くは、コンポーネントのネストを可能にする能力です。次の2つのコンポーネントを選択します。

var React = require('react');
var createReactClass = require('create-react-class');

var CommentList = reactCreateClass({
  render: function() {
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

var CommentForm = reactCreateClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

異なるコンポーネントの定義で、これらのコンポーネントをネストして参照することができます。

var React = require('react');
var createReactClass = require('create-react-class');

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList /> // Which was defined above and can be reused
        <CommentForm /> // Same here
      </div>
    );
  }
});

さらにネストするには3つの方法があります。いずれも使用する場所があります。

1.子供を使わずに入れ子にする

(上から続き)

var CommentList = reactCreateClass({
  render: function() {
    return (
      <div className="commentList">
        <ListTitle/>
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

これは、AがBを構成し、BがCを構成するスタイルです。

長所

  • UI要素を簡単かつ迅速に分離
  • 親コンポーネントの状態に基づいて子に小道具を簡単に注入できます

短所

  • コンポジション・アーキテクチャーの可視性の低下
  • 再利用性の低下

良い場合

  • BとCはちょうどプレゼンテーションコンポーネントです
  • BはCのライフサイクルを担当する必要があります

2.子どもを使ったネスティング

(上から続き)

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList>
            <ListTitle/> // child
        </CommentList>
        <CommentForm />
      </div>
    );
  }
});

これは、AがBを構成し、AがBにCを構成するよう指示するスタイルです。

長所

  • より良いコンポーネントライフサイクル管理
  • コンポジションアーキテクチャの可視性の向上
  • より良い再利用性

短所

  • 注入小道具は少し高価になることができます
  • 子コンポーネントの柔軟性と消費電力の削減

良い場合

  • Bは将来的にC以外の何かを作成するか受け入れなければならない
  • AはCのライフサイクルを制御する必要があります

Bはthis.props.childrenを使用してCをレンダリングし、Bがそれらの子が何であるかを知るための構造化された方法はありません。したがって、Bは小道具を追加することで子どもの構成要素を豊かにするかもしれませんが、Bが自分のものを正確に知る必要があれば、#3がより良い選択肢になるかもしれません。

3.小道具を使用してネスティングする

(上から続き)

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList title={ListTitle}/> //prop
        <CommentForm />
      </div>
    );
  }
});

これは、AがBを構成するスタイルであり、BはAが特定の目的のために何かを渡すためのオプションを提供する。より構造化された構成。

長所

  • 特徴としての構成
  • 簡単な検証
  • より良い合成性

短所

  • 注入小道具は少し高価になることができます
  • 子コンポーネントの柔軟性と消費電力の削減

良い場合

  • Bには何かを構成するために定義された特定の機能があります
  • Bは何をレンダリングするのか分からない

#3は、通常、構成要素の公立図書館を作成するための必須要素ですが、構成可能な構成要素を作成し、構成機能を明確に定義するための一般的な方法でもあります。 #1は動作するものを作るのに最も簡単で速いものですが、#2と#3はさまざまなユースケースで一定の利点をもたらすはずです。

コンポーネントの作成

これは基本的な例の拡張です:

基本構造

import React, { Component } from 'react';
import { render } from 'react-dom';

class FirstComponent extends Component {
    render() {
        return (
            <div>
                Hello, {this.props.name}! I am a FirstComponent.
            </div>
        );
    }
}

render(
    <FirstComponent name={ 'User' } />,
    document.getElementById('content')
);

上記の例は、 状態を含んでいない( ステートレスな要素と呼ばれます)。

そのような場合、 ES6の矢印機能に基づいたステートレス機能コンポーネントを使用する方が望ましいことがあります。

ステートレス機能コンポーネント

多くのアプリケーションでは、状態を保持するスマートコンポーネントがありますが、単純に小道具を受け取り、JSXとしてHTMLを返す単純なコンポーネントをレンダリングします。ステートレスな機能コンポーネントは、はるかに再利用可能で、アプリケーションに良いパフォーマンスをもたらします。

彼らは2つの主な特徴があります:

  1. レンダリングされると、それらは渡されたすべての小道具でオブジェクトを受け取ります
  2. レンダリングするJSXを返さなければなりません
// When using JSX inside a module you must import React
import React from 'react';
import PropTypes from 'prop-types';

const FirstComponent = props => (
    <div>
        Hello, {props.name}! I am a FirstComponent.
    </div>
);

//arrow components also may have props validation
FirstComponent.propTypes = {
    name: PropTypes.string.isRequired,
}

// To use FirstComponent in another file it must be exposed through an export call:
export default FirstComponent;

ステートフルコンポーネント

上記の「ステートレス」コンポーネントとは対照的に、「ステートフル」コンポーネントには、 setStateメソッドで更新できる状態オブジェクトがあります。状態をconstructorで初期化してから設定する必要があります。

import React, { Component } from 'react';

class SecondComponent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            toggle: true
        };

        // This is to bind context when passing onClick as a callback
        this.onClick = this.onClick.bind(this);
    }

    onClick() {
        this.setState((prevState, props) => ({
            toggle: !prevState.toggle
        }));
    }
    
    render() {
        return (
            <div onClick={this.onClick}>
                Hello, {this.props.name}! I am a SecondComponent.
                <br />
                Toggle is: {this.state.toggle}
            </div>
        );
    }
}

ComponentはなくPureComponentコンポーネントを拡張すると、浅い小道具と状態の比較によるshouldComponentUpdate()ライフサイクルメソッドが自動的に実装されます。これにより、発生する必要のないレンダリングの量を減らすことにより、アプリケーションのパフォーマンスが向上します。これは、あなたのコンポーネントが「Pure」であり、常に同じ出力を同じ状態と小道具の入力でレンダリングすることを前提としています。

高次コンポーネント

高次コンポーネント(HOC)は、コンポーネント機能を共有することを可能にします。

import React, { Component } from 'react';

const PrintHello = ComposedComponent => class extends Component {
    onClick() {
        console.log('hello');
    }
    
    /* The higher order component takes another component as a parameter 
    and then renders it with additional props */
    render() {
        return <ComposedComponent {...this.props } onClick={this.onClick} />
    }
}

const FirstComponent = props => (
    <div onClick={ props.onClick }>
        Hello, {props.name}! I am a FirstComponent.
    </div>
);

const ExtendedComponent = PrintHello(FirstComponent);

高次のコンポーネントは、レンダリング方法の違いにかかわらず、複数のコンポーネント間でロジックを共有する場合に使用されます。

setStateの落とし穴

非同期コンテキストでsetStateを使用する場合は注意が必要です。たとえば、get要求のコールバックでsetStateを呼び出すとします。

class MyClass extends React.Component {
    constructor() {
        super();

        this.state = {
            user: {}
        };
    }

    componentDidMount() {
        this.fetchUser();
    }

    fetchUser() {
        $.get('/api/users/self')
            .then((user) => {
                this.setState({user: user});
            });
    }

    render() {
        return <h1>{this.state.user}</h1>;
    }
}

これは問題を呼び出す可能性があります。 Componentマウント解除後にコールバックが呼び出された場合、 this.setStateは関数にはなりません。このような場合は必ず、 setState使用をsetStateことができるように注意する必要があります。

この例では、コンポーネントのマウント解除時にXHR要求を取り消すことができます。

class MyClass extends React.Component {
    constructor() {
        super();

        this.state = {
            user: {},
            xhr: null
        };
    }

    componentWillUnmount() {
        let xhr = this.state.xhr;

        // Cancel the xhr request, so the callback is never called
        if (xhr && xhr.readyState != 4) {
            xhr.abort();
        }
    }

    componentDidMount() {
        this.fetchUser();
    }

    fetchUser() {
        let xhr = $.get('/api/users/self')
            .then((user) => {
                this.setState({user: user});
            });

        this.setState({xhr: xhr});
    }
}

非同期メソッドは状態として保存されます。 componentWillUnmountでは、XHR要求をキャンセルすることを含め、すべてのクリーンアップを実行します。

もっと複雑なことをすることもできます。この例では、引数としてこのオブジェクトを受け取り、防ぎ私が作成しています「stateSetter」関数this.setState機能がときcancel呼ばれています:

function stateSetter(context) {
    var cancelled = false;
    return {
        cancel: function () {
            cancelled = true;
        },
        setState(newState) {
            if (!cancelled) {
                context.setState(newState);
            }
        }
    }
}

class Component extends React.Component {
    constructor(props) {
        super(props);
        this.setter = stateSetter(this);
        this.state = {
            user: 'loading'
        };
    }
    componentWillUnmount() {
        this.setter.cancel();
    }
    componentDidMount() {
        this.fetchUser();
    }
    fetchUser() {
        $.get('/api/users/self')
            .then((user) => {
                this.setter.setState({user: user});
            });
    }
    render() {
        return <h1>{this.state.user}</h1>
    }
}

これは、 cancelled変数が、作成したsetStateクロージャで表示されるためです。

小道具

小道具は、情報をReactコンポーネントに渡す手段です。関数を含む任意の型を持つことができます。コールバックと呼ばれることもあります。

JSXでは、属性構文を使ってpropsが渡されます

<MyComponent userID={123} />

MyComponentの定義の中で、userIDはpropsオブジェクトからアクセスできるようになりました

// The render function inside MyComponent
render() {
    return (
        <span>The user's ID is {this.props.userID}</span>
    )
}

すべてのprops 、その種類、適用可能な場合はそのデフォルト値を定義することが重要です。

// defined at the bottom of MyComponent
MyComponent.propTypes = {
    someObject: React.PropTypes.object,
    userID: React.PropTypes.number.isRequired,
    title: React.PropTypes.string
};

MyComponent.defaultProps = {
    someObject: {},
    title: 'My Default Title'
}

この例では、prop someObjectはオプションですが、prop userIDは必須です。 userIDMyComponentに指定しなかった場合、実行時にReactエンジンに必要な小道具が提供されていないことを警告するコンソールが表示されます。しかし、この警告はReactライブラリの開発版にのみ表示されます。生産版では警告は記録されません。

defaultProps使用すると、単純化することができます

const { title = 'My Default Title' } = this.props;
console.log(title);

console.log(this.props.title);

また、 object arrayfunctionsを使用するための保護手段です。オブジェクトにデフォルトの小道具を指定しないと、小道具が渡されなかった場合、次のエラーが発生します。

if (this.props.someObject.someKey)

上記の例では、 this.props.someObjectundefinedであるため、 someKeyのチェックによってエラーがスローされ、コードが破損します。 defaultPropsを使用すると、上記のチェックを安全に使用できます。

コンポーネントの状態 - 動的ユーザーインターフェイス

見出し(h3要素)があり、それをクリックすると見出しの名前を変更できるように、入力ボックスにしたいと考えています。 Reactは、コンポーネント状態とif else文を使用してこれを非常に簡単で直感的にします。 (以下のコードの説明)

// I have used ReactBootstrap elements. But the code works with regular html elements also
var Button = ReactBootstrap.Button;
var Form = ReactBootstrap.Form;
var FormGroup = ReactBootstrap.FormGroup;
var FormControl = ReactBootstrap.FormControl;

var Comment = reactCreateClass({
  getInitialState: function() {
    return {show: false, newTitle: ''};
  },

  handleTitleSubmit: function() {
     //code to handle input box submit - for example, issue an ajax request to change name in database
  },

  handleTitleChange: function(e) {
    //code to change the name in form input box. newTitle is initialized as empty string. We need to update it with the string currently entered by user in the form
    this.setState({newTitle: e.target.value});
  },

  changeComponent: function() {
    // this toggles the show variable which is used  for dynamic UI
    this.setState({show: !this.state.show)};
  },

  render: function() {

    var clickableTitle;

    if(this.state.show) {
        clickableTitle = <Form inline onSubmit={this.handleTitleSubmit}>
                             <FormGroup controlId="formInlineTitle">
                                 <FormControl type="text" onChange={this.handleTitleChange}>
                             </FormGroup>
                         </Form>;
    } else {
        clickabletitle = <div>
                            <Button bsStyle="link" onClick={this.changeComponent}>
                                <h3> Default Text </h3>
                            </Button>
                         </div>;
    }

    return (
        <div className="comment">
            {clickableTitle}
        </div>
    );
  }
});

ReactDOM.render(
    <Comment />, document.getElementById('content')
);

コードの主要部分はclickableTitle変数です。状態変数showに基づいて、Form要素かButton要素のいずれかになります。 Reactはコンポーネントの入れ子を可能にします。

そこで、{clickableTitle}要素をレンダリング関数に追加することができます。 clickableTitle変数を探します。 'this.state.show'という値に基づいて、対応する要素が表示されます。

ステートレス機能コンポーネントのバリエーション

const languages = [
  'JavaScript',
  'Python',
  'Java',
  'Elm',
  'TypeScript',
  'C#',
  'F#'
]

// one liner
const Language = ({language}) => <li>{language}</li>

Language.propTypes = {
  message: React.PropTypes.string.isRequired
}

/**
* If there are more than one line.
* Please notice that round brackets are optional here,
* However it's better to use them for readability
*/
const LanguagesList = ({languages}) => {
  <ul>
    {languages.map(language => <Language language={language} />)}
  </ul>
}

LanguagesList.PropTypes = {
  languages: React.PropTypes.array.isRequired
}

/**
 * This syntax is used if there are more work beside just JSX presentation
 * For instance some data manipulations needs to be done.
 * Please notice that round brackets after return are required,
 * Otherwise return will return nothing (undefined)
 */
const LanguageSection = ({header, languages}) => {
  // do some work
  const formattedLanguages = languages.map(language => language.toUpperCase())
  return (
    <fieldset>
      <legend>{header}</legend>
      <LanguagesList languages={formattedLanguages} />
    </fieldset>
  )
}

LanguageSection.PropTypes = {
  header: React.PropTypes.string.isRequired,
  languages: React.PropTypes.array.isRequired
}

ReactDOM.render(
  <LanguageSection 
    header="Languages" 
    languages={languages} />,
  document.getElementById('app')
)

ここではその実例を見つけることができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow