react 入門 3
これまで、入門1では、コンポーネントという形でファイル毎に分割する方法、JSXによりHTMLの役割をjavascriptに組み込む方法、コンポーネントに読み取り専用の引数を与える方法を示しました。
入門2では、コンポーネントにそれぞれの内部の状態を変数として保持する方法、イベントにより内部の関数を呼び出し、状態変数を更新し表示に反映する方法を学びました。
入門3では、JSX内で、動的に別のJSXを生成、選択する方法を示します。
JSXの動的な選択、追加や削除
JSXのループ生成と選択について、例をつかって説明します。次のように、都市の選択リストと選択された都市に応じたメッセージの表示です。
index.html
いつものテンプレートです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>test</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js
Forコンポーネントを呼び出しています。また、Forコンポーネントには、選択される都市の名前とIDがセットになったJSONオブジェクトの配列を読み取り専用の引数、localesという名前のpropsとして渡しています。
import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import For from './For'
const list_locale = [
{
"locale":"東京",
"locale_id":"tokyo"
},
{
"locale":"神奈川",
"locale_id":"kanagawa"
},
{
"locale":"大阪",
"locale_id":"osaka"
},
]
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<StrictMode>
<For locales={list_locale}/>
</StrictMode>
)
For.js
ForコンポーネントはJSXとして、上位からPropsとして渡された都市をoption要素として選択できるselect要素と、選択された都市を表示するp要素、選択された都市を渡すとメッセージを返すIfコンポーネントを返します。
状態変数として、選択された都市名を保存するStateを持ちます。また、ループ処理でselectのoptionをJSXの配列として変数に保存します。
JSXを返す部分では、このoptionをJSXの配列が入った変数を{}で括って表示します。JSXは文字列ではないので、たとえば”+”演算子で繋げたりすることはできません。JSXは、変数に格納できる式で、さらにいうとJSX のそれぞれの要素は React.createElement() を呼ぶための単なる糖衣構文です。
とりあえず、JSXの中で別のJSXを呼び出す際にはJSXが格納された変数を{}で括って記載すること、変数はJSXの配列でも問題なく表示されることを覚えておいてください。
import { useState } from "react"
import If from "./If"
const For = (props) => {
const [locale,setLocale] = useState(props.locales[0].locale)
const list_jsx_options = []
for(let i=0; i<props.locales.length;i++){
const jsx = <option value={props.locales[i].lcale_id} key={i}>{props.locales[i].locale}</option>
list_jsx_options.push(jsx)
}
const handle_select_locale = (e) =>{
setLocale(e.target.value)
}
return(
<div>
<select onChange={handle_select_locale} name="locale">
{list_jsx_options}
</select>
<p>{locale}が選択されました</p>
<If locale={locale}/>
</div>
)
}
export default For
セレクト要素で選択された都市が変化すると、handle_select_localeが呼び出されて、State変数が書き換えられます。
Ifコンポーネントには、State変数が、propsとして渡されています。
If.js
Ifコンポーネントでは、以下のように、PropsによりJSX変数のmessageを選択してreturnの一部として返しています。コンポーネントは、必ず最上位のタグを1つ持つ必要があります。ここでは、message自体がタグを持ったり持たなかったりしているので、sectionタグでmessageを囲っています。
const If = (prop)=>{
let message = ""
if(prop.locale === "東京"){
message = <h3>"大雨のため中止になりました"</h3>
}else if(prop.locale === "大阪"){
message = <h4>"雨です。注意してください"</h4>
}
return(
<section>{message}</section>
)
}
export default If
削除?
index.jsのlist_localeから大阪を削除して下記の部分を削除してみてください。For.jsにそもそも大阪の情報が渡されず、レンダリングされなくなりました。
const list_locale = [
{
"locale":"東京",
"locale_id":"tokyo"
},
{
"locale":"神奈川",
"locale_id":"kanagawa"
},
]
しかし、誰が再レンダリングを命じたのでしょうか。reactにおいて、レンダリング、関数コンポーネントの再呼び出しは次の時に発生します。
stateが更新された時
propsが更新された時
親コンポーネントが再レンダリングされた時
便利ですね。ただ、reactが要求する設計思想が、この動作からわかります。実際に描画に関するコンポーネントは末端に配置しましょう。
おまけ:JSのループ
Forコンポーネントのlist_jsx_optionsは次のようにForEachで書くこともできます。
const list_jsx_options = []
props.locales.forEach((item,index) => {
const jsx = <option value={item.lcale_id} key={index}>{item.locale}</option>
list_jsx_options2.push(jsx)
});
あるいはmap関数を活用してシンプルに書くこともできます。
const list_jsx_options = props.locales.map((item,index) =>
<option value={item.lcale_id} key={index}>{item.locale}</option>
)
この記事が気に入ったらサポートをしてみませんか?