Hello, world!
React は、インタラクティブなユーザインターフェイスの作成にともなう苦痛を取り除きます。アプリケーションの各状態に対応するシンプルな View を設計するだけで、React はデータの変更を検知し、関連するコンポーネントだけを効率的に更新、描画します。
宣言的な View を用いてアプリケーションを構築することで、コードはより見通しが立ちやすく、デバッグのしやすいものになります。
自分自身の状態を管理するカプセル化されたコンポーネントをまず作成し、これらを組み合わせることで複雑なユーザインターフェイスを構築します。
コンポーネントのロジックは、Template ではなく JavaScript そのもので書くことができるので、様々なデータをアプリケーション内で簡単に取り回すことができ、かつ DOM に状態を持たせないようにすることができます。
React と組み合わせて使用する技術に制限はありません。React を使って新しい機能を追加する際に、既存のソースコードを書き換える必要はありません。
React は Node を使ったサーバ上でもレンダーできますし、React Native を使うことでモバイルアプリケーションの中でも動きます。
React コンポーネントを作成するには render()
メソッドを実装します。このメソッドは、受け取った入力データを元に、表示する内容を返す役割を担当します。次の例では JSX と呼ばれる XML に似た構文を使っています。コンポーネントに渡された入力データを this.props
で参照し、render()
の中で使用しています。
React を使う際に JSX を必ず使わなくてはいけないわけではありません。 JSX のコンパイルによって生成される生の JavaScript コードを見るには、Babel REPL を参照してください。
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
root.render(<HelloMessage name="Taylor" />);
コンポーネントは、入力されたデータを受け取るだけではなく(受け取ったデータは this.props
で参照することができます)コンポーネント独自の内部状態を持つこともできます(これは this.state
で参照することができます)。状態が変化した場合には、render()
が再度実行され、描画されるマークアップが更新されます。
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
tick() {
this.setState(state => ({
seconds: state.seconds + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}
}
root.render(<Timer />);
props
と state
を組み合わせることで、ちょっとした Todo アプリケーションを作ることができます。次の例では state
を用いて、現在の Todo リストのアイテムの状態を追跡しています。それからユーザが入力したテキストに関しても state
で管理しています。イベントハンドラは、それが書かれた要素内部にレンダーされるように一見思われますが、実際にはこれらのハンドラは集められて、イベントデリゲーションを用いて実装されます。
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = { items: [], text: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<label htmlFor="new-todo">
What needs to be done?
</label>
<input
id="new-todo"
onChange={this.handleChange}
value={this.state.text}
/>
<button>
Add #{this.state.items.length + 1}
</button>
</form>
</div>
);
}
handleChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newItem = {
text: this.state.text,
id: Date.now()
};
this.setState(state => ({
items: state.items.concat(newItem),
text: ''
}));
}
}
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}
}
root.render(<TodoApp />);
React は柔軟性が高いので、React 以外のライブラリやフレームワークとやり取りをするためのフックを提供しています。次の例では Markdown の外部ライブラリである remarkable を使用しています。<textarea>
に入力された値をリアルタイムに HTML へと変換しています。
class MarkdownEditor extends React.Component {
constructor(props) {
super(props);
this.md = new Remarkable();
this.handleChange = this.handleChange.bind(this);
this.state = { value: 'Hello, **world**!' };
}
handleChange(e) {
this.setState({ value: e.target.value });
}
getRawMarkup() {
return { __html: this.md.render(this.state.value) };
}
render() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<label htmlFor="markdown-content">
Enter some markdown
</label>
<textarea
id="markdown-content"
onChange={this.handleChange}
defaultValue={this.state.value}
/>
<h3>Output</h3>
<div
className="content"
dangerouslySetInnerHTML={this.getRawMarkup()}
/>
</div>
);
}
}
root.render(<MarkdownEditor />);
Hello, world!