Reactとは何なのか?Reactの超基礎をまとめています。
※現在、Reactは関数コンポーネントで書くのが一般的ですが、本記事は以前の記法であるclassコンポーネントとなっております。
.jsファイルの構成
Reactのファイル.jsの構成について見てみます。
import React from 'react'; Reactをimport
class App extends React.Component { React.Componentを継承するクラスの定義
render() { JSXを戻り値とするrenderメソッドを定義
const text = 'Hello';
return (
<div> { text } </div>
);
}
}
export default App; クラスをexport
JSX
JSXとは何か?
Reactで、見た目を作るコードを書くファイルのことです。
つまり、HTMLの役割をするものです。
JSXの特徴
render() {
return (
<div>
<h1>heading</h1>
<p>paragraph</p>
</div>
);
}
コメントの書き方
{/*コメント*/}
JavaScriptの場合(returnの外)
// コメント
imgタグの書き方
<img src='https://〜.jpg'/>
イベント
イベントの使い方を見ていきます。
<button イベント名 = { () => { 処理 } }></button>
例
<button onClick = { () => { 処理 } }></button>
処理をconsole.logとする場合
<button onClick = { () => { console.log('ボタン') } }></button>
state
Reactの最もポピュラーなhook、stateについて見ていきましょう!
stateとは、ユーザーの動きに合わせて変わる値です。
例えば、ボタンを押すとstateが変わり、表示が変更される。といった使い方をします。
constructor(props)
super(props);
this.state = { name: 'コーヒー' }
}
render() {
console.log(this.state);
return (
> { name: 'コーヒー' }
ここで定義したオブジェクト{ name: ‘コーヒー’ }が、stateの初期値です。
constructorやsuperは定型文なのでこのまま覚えましょう!
定義したstateはthis.stateで取得できます。
上記はオブジェクトを出力する方法でしたが、値を取得する場合は以下のように.nameとします。
constructor(props)
super(props);
this.state = { name: 'コーヒー' }
}
render() {
return (
<h1>朝は{this.state.name}から始まる</h1>
);
}
指定されたプロパティに対応するstateの値を変更する
stateの値を変更するには、setStateを使います。
this.setState({プロパティ名: 変更する値})
ボタンクリックで名前の表示を変える例を見ます。
constructor(props) {
super(props);
this.state = {name: 'にんじゃわんこ'};
}
render() {
return (
<div>
<h1>こんにちは、{this.state.name}さん!</h1>
<button onClick={() => {this.setState({name:'ひつじ仙人'})}}>ひつじ仙人</button>
<button onClick={() => {this.setState({name:'にんじゃわんこ'})}}>にんじゃわんこ</button>
</div>
);
}
{name:’ひつじ仙人’}は切り替え表示する文字、「ひつじ仙人」はビューに表示している文字です。
メソッド化
メソッドは以下のように定義することができる。
class クラス名 {
constructor(){
}
メソッド名() {
行いたい処理
}
}
constructor(props) {
super(props);
this.state = {name: 'にんじゃわんこ'};
}
handleClick(name) {
this.setState({name: name});
}
render() {
return (
<button onClick={() => {this.setState({name:'ひつじ仙人'})}}>ひつじ仙人</button>
<button onClick={() => {this.setState({name:'にんじゃわんこ'})}}>にんじゃわんこ</button>
);
}
handleClickというメソッドを作り、その中でsetStateのnameプロパティの値を変更する処理を行います。
handleClickメソッドを呼び出すときに、引数nameに「ひつじ仙人」「にんじゃわんこ」が渡され、メソッドhandleClick(name)で、引数が以下のように変更となります。
{this.setState({name: 'ひつじ仙人'})}
↓
{this.handleClick('ひつじ仙人')}
カウントアップ機能を作る
カウントアップ機能を作ります。
stateの定義、stateの表示
constructor(props) {
super(props);
this.state = {count: 0};
}
render() {
return (
<div>
<h1>
{this.state.count}
</h1>
<button>+</button>
</div>
);
}
stateの変更
stateを変更し、ボタンをクリックしたときに呼び出されるメソッドを定義します。
handleClick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div>
<h1>
{this.state.count}
</h1>
<button onClick={()=>{this.handleClick()}}>+</button>
</div>
);
}
Reactの表示の仕組み
Reactのコードを実際にブラウザに表示するには、App.js以外にもindex.jsとindex.htmlというファイルが必要になります。
App.jsのJSXのHTMLへの変換の仕方
index.js内でindex.htmlのid=”root”を取得し、Appを渡して、App.jsが表示されている。
<!DOCTYPE html>
<html>
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
import React from 'react';
class App extends React.Component {
render() {
return (
<div>
<h1>Hello World</h1>
<p>一緒にReactを学びましょう!</p>
</div>
);
}
}
export default App;
これによりHTMLに変換されています。
CSSの読み込み
index.html内でstylesheet.cssを読み込みます。
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="stylesheet.css">
<title>React App</title>
</head>
タグ(要素)のCSSの書き方
class App extends React.Component {
render() {
return (
<div>
<h1>Hello World</h1>
<p>一緒にReactを学びましょう!</p>
</div>
);
}
}
h1 {
color: red;
}
p {
color: blue;
}
こんなふうに、普通の記法でOKです。
classのCSSの書き方
class App extends React.Component {
render() {
return (
<div>
<h1 className='title'>Hello World</h1>
<p className='text'>Hello React</p>
</div>
);
}
}
.title {
color: red;
}
.text {
color: blue;
}
コンポーネントについて
Reactでは見た目を機能毎にコンポーネント化しています。
むしろそれこそがReact!
import React from 'react';
class Language extends React.Component {
render() {
return (
JSX
);
}
}
コードの説明
①Reactをインポート
②React.Componentを継承するクラスを定義
③renderメソッドを定義 JSXを戻り値とする
これがコンポーネント作成の雛形!
Languageコンポーネントのブラウザでの表示の流れ
Language.js → App.js → index.js → index.html
App.jsでLanguageコンポーネントを呼び出す必要があり、
以下のようにLanguage.js内でLanguageコンポーネントをexportします。
import React from 'react';
class Language extends React.Component {
render() {
return (
JSX
);
}
}
export default Language;
App.jsの方では、以下変更を加えます。
- Languageコンポーネントのimport
- JSX内に<コンポーネント/>を記述
import React from 'react';
import Language from './Language';
class App extends React.Component {
render() {
return (
<div>
<h1>Hello World</h1>
<Language/>
</div>
);
}
}
上記の<Language/>の数だけコンポーネントを呼び出す(表示する)ことができます。
このコンポーネントのHTML、CSSを変更していきます。
App.jsからLanguage.js(コンポーネント)にデータを渡します。
class App extends React.Component {
render() {
return (
<div>
<Language
name = '名前'
image = '画像'
/>
</div>
);
}
}
ここで、name, imageをpropsと言いいます。
propsの受け取り
Languageコンポーネント側でpropsを受け取ります。
this.propsで受け取りができます。
class Language extends React.Component {
render() {
console.log( this.props );
return (
JSX
);
}
}
>
{
name: "名前"
image: "画像"
}
propsの値の取得
{this.props.name}
画像の場合
<img src={this.props.image} />
上記のように、propsを使うことで、1つのコンポーネントに複数の値を入れることができます。
しかし、それらを一つずつ取得するのは大変です。
そこで、mapメソッドを使用します。
mapメソッド使用例
class App extends React.Component {
render() {
return (
<div>
<h1>言語一覧</h1>
<div className='language'>
<Language
name='HTML & CSS'
image='https://~'
/>
<Language
name='JavaScript'
image='https://~'
/>
<Language
name='React'
image='https://~'
/>
</div>
</div>
);
}
}
mapメソッドを使用すると、以下のように書き換えられる。
class App extends React.Component {
render() {
const languageList = [
{
name: 'HTML & CSS',
image: 'https://~'
},
{
name: 'JavaScript',
image: 'https://~'
},
{
name: 'React',
image: 'https://~'
}
];
return (
<div>
<h1>言語一覧</h1>
<div className='language'>
{languageList.map((languageItem) => {
return (
<Language
name={languageItem.name}
image={languageItem.image}
/>
)
})}
</div>
</div>
);
}
}
languageListという配列を作成し、mapメソッドを用いて1つずつオブジェクトを取り出し、Languageコンポーネントを呼び出し、その中でpropsを渡します。
propsを渡すとは、LanguageItem→languageItem.nameやlanguageItem.imageに渡すことを言います。
モーダル
モーダルの作成手順
- コンポーネントの中にモーダルのJSXを追加する
- 初期状態でモーダルを隠す
- モーダルの表示・非表示を設定
モーダルが表示されているかそうでないかは、stateを使って判定します。
constructorを定義し、stateを定義します。
そして、stateのプロパティ名にisModalOpenを定義し、初期値をfalseとします。
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen:false}
};
この時点ではモーダルは表示され続けています。
そのため、isModalOpenがtrueのときだけモーダルが表示されるというようにします。
① 変数modalを定義
② stateのModalがtrueのとき、変数modalに、モーダルのJSXを代入する
③ return内で、モーダルJSXを変数modalに書き換える
render() {
let modal;
if (this.state.isModalOpen){
modal = (
<div className='modal'>
<div className='modal-inner'>
<div className='modal-header'></div>
<div className='modal-introduction'>
<h2>{this.props.name}</h2>
<p>{this.props.introduction}</p>
</div>
<button className='modal-close-btn'>
とじる
</button>
</div>
</div>
);
}
return (
<div className='lesson-card'>
<div className='lesson-item'>
<p>{this.props.name}</p>
<img src={this.props.image} />
</div>
{modal}
</div>
);
}
ifを使って条件を付けたことで、初期状態でモーダルが隠れるようになりました。
次は、クリック時にモーダルが表示されるようにします。
① stateを変更するhandleClickLessonメソッドを定義する。
② そして、isModalOpenの値をtrueにする処理をする
③rerurn内にonClickイベントを追加し、 クリック時にhandleClickLessonを呼び出されるようにする。
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}
handleClickLesson () {
this.setState({isModalOpen:true});
}
render() {
let modal;
if (this.state.isModalOpen) {
modal = (
<div className='modal'>
<div className='modal-inner'>
<div className='modal-header'></div>
<div className='modal-introduction'>
<h2>{this.props.name}</h2>
<p>{this.props.introduction}</p>
</div>
<button className='modal-close-btn'>
とじる
</button>
</div>
</div>
);
}
return (
<div className='lesson-card'>
<div
className='lesson-item'
onClick={() => {this.handleClickLesson()}}
>
<p>{this.props.name}</p>
<img src={this.props.image} />
</div>
{modal}
</div>
);
}
}
あとは、モーダルを「とじる」ボタンで閉じれるようにするだけ!
上記のモーダル表示のクリックイベントと同様に、「とじる」のクリックイベントを作成する。
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}
handleClickLesson() {
this.setState({isModalOpen: true});
}
handleClickClose () {
this.setState({isModalOpen:false});
}
render() {
let modal;
if (this.state.isModalOpen) {
modal = (
<div className='modal'>
<div className='modal-inner'>
<div className='modal-header'></div>
<div className='modal-introduction'>
<h2>{this.props.name}</h2>
<p>{this.props.introduction}</p>
</div>
<button
className='modal-close-btn'
onClick={() => {this.handleClickClose()}}
>
とじる
</button>
</div>
</div>
);
}
return (
<div className='lesson-card'>
<div
className='lesson-item'
onClick={() => {this.handleClickLesson()}}
>
<p>{this.props.name}</p>
<img src={this.props.image} />
</div>
{modal}
</div>
);
}
}
お問い合わせフォームの作成
モーダルの作成ができたところで、次は、お問い合わせフォームの作成をします。
見た目(JSX)を作成
class ContactForm extends React.Component {
render() {
return (
<div className='contact-form'>
<form>
<p>メールアドレス(必須)</p>
<input />
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type = 'submit'
value = '送信'
/>
</form>
</div>
);
}
}
送信完了時に表示するメッセージを準備する
フォームが送信されたかどうかはstateで管理します。
送信されていなければstateはfalseとしたいので、初期値はfalseに設定する。
空の変数contactFormを定義し、isSubmittedで条件分岐します。
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
isSubmitted:false
};
}
render() {
let contactForm
if (this.state.isSubmitted) {
contactForm = (
<div className='contact-submit-message'>
送信完了
</div>
);
} else {
contactForm = (
<form>
<p>メールアドレス(必須)</p>
<input />
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type='submit'
value='送信'
/>
</form>
);
}
return (
<div className='contact-form'>
{ contactForm }
</div>
);
}
}
メッセージを表示する
送信されたら表示が切り替わるようにするには以下の形式で記述します。
<form onSubmit={() => {処理}}>
</form>
handleSubmit() {
this.setState({isSubmitted: true});
}
render() {
let contactForm;
if (this.state.isSubmitted) {
contactForm = (
<div className='contact-submit-message'>
送信完了
</div>
);
} else {
contactForm = (
<form onSubmit={() => {this.handleSubmit()}}>
<p>メールアドレス(必須)</p>
<input />
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type='submit'
value='送信'
/>
</form>
);
}
handleSubmitメソッドを定義して、
フォーム送信時に handleSubmitメソッド が実行されるようにonSubmitイベントを追加しました。
stateでフォームに入力された値を管理する
フォームに入力された値を、statewを使って取得します。
①stateにemailの項目を追加する。
②input タグにstateのemailを指定して表示する。
constructor(props) {
super(props);
this.state = {
isSubmitted: false,
email:'mail@prog-8.com'
};
}
handleSubmit() {
this.setState({isSubmitted: true});
}
render() {
let contactForm;
if (this.state.isSubmitted) {
contactForm = (
<div className='contact-submit-message'>
送信完了
</div>
);
} else {
contactForm = (
<form onSubmit={() => {this.handleSubmit()}}>
<p>メールアドレス(必須)</p>
<input value={this.state.email} />
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type='submit'
value='送信'
/>
</form>
);
}
onChangeイベントを追加して、入力値を取得し、consoleに出力します。
<input
value={this.state.email}
onChange={(event) => {console.log(event.target.value)}}
/>
inputタグのonChangeイベントで、handleEmailChangeメソッドの引数eventに値を渡し、
新たに定義したhandleEmailChangeというメソッドで、stateのemailを更新します。
handleEmailChange(event) {
const inputValue = event.target.value;
this.setState({email:inputValue})
}
handleSubmit() {
this.setState({isSubmitted: true});
}
render() {
let contactForm;
if (this.state.isSubmitted) {
contactForm = (
<div className='contact-submit-message'>
送信完了
</div>
);
} else {
contactForm = (
<form onSubmit={() => {this.handleSubmit()}}>
<p>メールアドレス(必須)</p>
<input
value={this.state.email}
onChange={(event) => {this.handleEmailChange(event)}}
/>
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type='submit'
value='送信'
/>
</form>
);
}
フォーム入力エラーメッセージを表示する
hasEmailErrorというstateを初期値falseで定義します。
emailErrorText変数を定義し、hasEmailErrorの値によってエラーメッセージの表示・非表示を切り替える条件式を設定します。
constructor(props) {
super(props);
this.state = {
isSubmitted: false,
email: '',
hasEmailError: false
};
}
handleEmailChange(event) {
const inputValue = event.target.value;
this.setState({email: inputValue});
}
handleSubmit() {
this.setState({isSubmitted: true});
}
render() {
let emailErrorText
if (this.state.hasEmailError) {
emailErrorText = (
<p className='contact-message-error'>
メールアドレスを入力してください
</p>
);
}
let contactForm;
if (this.state.isSubmitted) {
contactForm = (
<div className='contact-submit-message'>
送信完了
</div>
);
} else {
contactForm = (
<form onSubmit={() => {this.handleSubmit()}}>
<p>メールアドレス(必須)</p>
<input
value={this.state.email}
onChange={(event) => {this.handleEmailChange(event)}}
/>
{emailErrorText}
<p>お問い合わせ内容(必須)</p>
<textarea />
<input
type='submit'
value='送信'
/>
</form>
);
}
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
isSubmitted: false,
email: '',
hasEmailError: false,
};
}
handleEmailChange(event) {
const inputValue = event.target.value;
/* 定数isEmptyを定義し、入力チェックの結果を代入 */
const isEmpty = inputValue === ''
/* setStateを使ってemailとhasEmailErrorを一緒に更新 */
this.setState({
email: inputValue,
hasEmailError: isEmpty
});
}
以上で、お問い合わせフォームを作成することができました!
お読みいただきありがとうございました。
コメント