ブラウザに表示
render(){
return(
<h1>Hello World</h1>
);
} →Hello World
App.jsファイルのrenderメソッド内にあるreturnを見る。
そこにHTMLの様に表示させたい文字を記述するとそれがブラウザに表示される。
例:<h1>Hello World</h1>と記述→ Hello World と表示される。
このreturn内に記述するHTMLは「JSX」と言う!
JSXの書き方
エラーパターン
render(){
return(
<h1>h1です</h1>
<h2>h2です</h2>
<p>pです</p>
);
}
正常パターン
render(){
return(
<div>
<h1>h1です</h1>
<h2>h2です</h2>
<p>pです</p>
</div>
);
}
JSXはHTML(<h1><h2><p><div>等)と同様に記述することができる。
しかし、return内に複数の要素があるとエラーになる。
複数の要素がある場合は<div>タグで囲み、1つの要素としてまとめてあげる。
imgタグの注意点
render(){
return(
<img src="○○.png" />
);
}
JSXでimgタグを使用する場合、閉じタグが必要になります。
<img src=”○○.png” />のように、タグの終わりにスラッシュ「/」を記述します。
App.jsの構成
import React from "react"; ←Reactをインポート
class App extends React.Component{ ←React.Componentを継承するクラスの定義
render(){ ←¬
JSXに書く部分 JSXを戻り値とするrenderメソッドの定義
} ←」
}
export default App; ←クラスをエクスポート
App.jsはこの要素で構成されています。
App.jsを作成する時はいつもこのように書くので覚える必要はない。
JSXとJSの記述場所
class App extends React.Component { |
render() { |
return ( classから終わりの}までJS部分
ここがJSX部分 |
); |
} |
} |
JSXとJSの記述部分は分かれている。
JSXは、return内で記述し、記述された要素はブラウザに表示される。
jsは、classの始まりから終わりまで(return以外)の範囲で記述する。
JavaScriptを記述する
class App extends React.Component {
render() {
const text="Hello World";
return (
~
);
}
}
renderメソッド内でも、return外ではJavaScriptを記述できる。なので定数などを準備できる。
上記ではrenderメソッド内でJavaScriptで定数textを定義しているが、return外なので記述することが出来る。
JSXにJSを埋め込む
render() {
const text="Hello World";
return (
<div>{text}</div> →出力時にHello Worldが表示される。
);
}
---------------
例
import React from 'react';
class App extends React.Component {
render() {
const name = 'ねこ'; ←①return外のrender内で定数を準備
const imgUrl = 'neko.png';
return (
<div>
<h1>{name}</h1> ←② ①で準備した定数をreturn内で呼んで使用
<img src={imgUrl} />
</div>
);
}
}
export default App; →ねこ
画像
return内のJSXにJavaScriptを埋め込むことも出来る。
その場合、JavaScriptの部分を中括弧{ }で囲む。
タグの属性値(imgで言うとhttps://~~.png部分)も同様に中括弧{ }で記述出来る。
なので、return外で準備した定数(①)などを呼んで使用できる。(②)
JSXとJSのコメント
render(){
//ここはコメントです
return(
<div>
{/*ここはコメントです*/}
</div>
);
}
JSXは、{/* */}で囲むとコメントになる。
JavaScriptは、//を文頭に書くとコメントになる。
クリックや表示切替
ユーザーがボタンをクリックしたときに表示名が
切り替わるなどの処理をしたい場合には、Reactでは
イベントとstateという2つの武器が必要。
とりあえず先にクリックするボタンの作り方は、、
render(){
return(
<div>
<button>A</button>
<button>B</button>
</div>
);
}
イベントとは
「何かが起きた時、処理を実行するもの」
例:ボタンクリック時、表示処理を実行。など
イベントは「処理を指定するフェーズ」。画面表示はまだ変わらない!
イベントの書き方
<button イベント名={()=>{処理}}></button>
アロー関数を使ってイベント名={() => { 処理 }}とすると
指定したタイミングで処理を実行できる。
アロー関数はJavaScriptのため、{}で囲むことに注意
onClickイベント
<button onclick={()=>{処理}}> </button>
例
<div>
<button onclick={()=>{console.log("村人")}}>村人</button>
<button onclick={()=>{console.log("道具屋")}}>道具屋</button>
</div>
onClickイベントは「クリック時に処理を実行する」もの
イベント名にonClickを指定し、<button onClick={() => {処理}}>とする。
stateとは
stateは、ボタンクリック時に表示が変わるなどの、ユーザーの動きに合わせて変化する値。
イベントで指定した処理を「画面に反映させる」フェーズ
表示変更の流れは「stateの定義→表示→変更」
例:ボタンクリック時、それに合わせて「こんにちは、◯◯さん!」の
◯◯という名前の部分を変える。(ボタンを押すとstateが変わり、表示される名前が変わる)
オブジェクトの復習
const user = { name: "仙人", age: 99 }; ←この場合、プロパティはname、値は仙人。プロパティはage、値は99
console.log(user.age); ←「定数名.プロパティ名」で値を取得
→99
stateの定義について学習する前に「オブジェクト」について復習。
オブジェクトは上図のように、複数の値をプロパティという名前をつけて管理できるもの。
stateの定義ではこのオブジェクトを使っていく!
stateの定義
constructor(props){
super(props);
this.state = {name:"冒険者"}; ←まずstateの初期値を定義(オブジェクト使用)
}
例
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {name: '仙人'};
}
render() {
return (
<div>
<h1>こんにちは、仙人さん!</h1>
<button onClick={() => {console.log('仙人')}}>仙人</button>
<button onClick={() => {console.log('うさぎ')}}>うさぎ</button>
</div>
);
}
}
export default App; →こんにちは、仙人さん!
仙人(ボタン型表示) うさぎ(ボタン型表示)
stateは、constructor内でオブジェクトの形で定義する。
ここで定義したオブジェクトがstateの初期値となる。
「constructor(props)」や「super(props);」の記述ははいつも同じため、定型文として覚えればOK
stateの取得
console.log(this.state); →定数の全体を表示
{this.state.name} →定数の値を表示
class App extends React.Component {
constructor(props) {
super(props);
this.state = {name: '仙人'};
}
render() {
console.log(this.state);
return (
<h1>こんにちは、{this.state.name}さん!</h1>
);
} →{name: '仙人'}
→こんにちは、仙人さん!
定義したstateを表示できるようにしよう!
定義したstateは、this.stateで取得することができます。
console.log(this.state)をすると、オブジェクト自体が出力されます。
this.state.プロパティ名とすると、値が出力されます。
stateの変更(ここから画面表示も変わる)
this.setState({プロパティ名: "変更する値"});
例
import React from 'react';
class App extends React.Component {
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>
);
}
}
export default App;
→こんにちは、亀さん!(ボタン押下後これに表示が変わる)
こんにちは、うさぎさん!(ボタン押下後これに表示が変わる)
値を変更したい場合は、setStateを使う!
this.setState({プロパティ名: 変更する値})とすることで、プロパティ値を変更できる。
今回はボタンがクリックされた時に名前の値を変えるため、onClick内でsetStateを行う。
メソッド化
メソッドは処理のまとまりを定義できるもの。
「クリック時に表示名を変更する処理」をメソッド化してみよう!
メソッドの定義(class内関数)
メソッド名() { 処理 }
メソッドは関数と似たようなもので、中括弧{ }内に行いたい処理を記述する。
今回はstateの「nameプロパティ値を変更する処理」を行
うhandleClickメソッドを作る。
handleClickメソッドを定義し、stateを変更する処理を追加しよう。
例
class App extends React.Component {
handleClick(){ ←stateの値をhandleClickメソッドを定義して変更する記述
stateのnameプロパティ値を変更する処理
}
}
メソッドを呼び出す
例
class App extends React.Component {
handleClick(){
stateのnameプロパティ値を変更する処理
}
}
<button onClick={() => {this.handleClick()}}>仙人</button>
メソッドはイベント内で呼び出すこともできる。
例:onClick={() => {this.メソッド名()}}とすることで、
クリック時にApp.js内の指定したメソッドを実行することができる。
App.js内のメソッドを指定する時、thisを使う。
メソッドに引数を渡す
例
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {name: '仙人'};
}
handleClick(name) {
this.setState({name: name});
}
render() {
return (
<div>
<h1>こんにちは、{this.state.name}さん!</h1>
<button onClick={() => {this.handleClick('仙人')}}>仙人</button>
<button onClick={() => {this.handleClick('うさぎ')}}>うさぎ</button>
</div>
);
}
}
export default App;
ここではメソッドに引数を渡せるようにする。
6行目でもともとのstateのname値が定義される。
8,9行目でメソッド化したhandleClickメソッドで、クリック時に名前が変わる処理をまとめてる。
そこに15,16のクリック時にhandleClickの引数が8行目に引き渡してそれが処理内で引数で値使われて戻される。
カウントアップ機能を実装
まずは、「stateの定義」と「stateの表示」を実装する。(ボタンを押せるだけでまだ増えない)
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
// stateの定義
this.state = {count: 0};
}
render() {
return (
<div>
<h1>
// stateの表示
{this.state.count}
</h1>
<button>+</button>
</div>
);
}
}
export default App;
次にボタンをクリックした時にカウントアップするようにしていこう。
クリックした時のイベントなのでonClickイベントを使いましょう。
「stateの変更」
stateのcount値に1を足すメソッドを定義して、
+ボタンをクリックしたときに、1を足すメソッドを作ります。後でそのメソッドを呼び出すようにします。
stateのcount値に1を足すことで、表示されるカウントも1足されたものが表示されます。
・メソッド(stateのcount値を+1する処理のメソッド)を準備
handleClick() {
this.setState({count: this.state.count + 1});
}
・+ボタンをクリック時、handleClickメソッドを呼び出す処理
<button onClick={() => {this.handleClick()}}>+</button>
まとめると↓
例
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
}
handleClick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div>
<h1>
{this.state.count}
</h1>
<button onClick={() => {this.handleClick()}}>+</button>
</div>
);
}
}
export default App;
Reactの表示の仕組み
Reactの表示の仕組み:ブラウザに表示される流れ
・表示の流れ
(app.js) →JSXの状態 →(index.js) → HTMLの状態 →(index.html)
・ファイル構造
Reactフォルダ- index.html
|
L srcフォルダ- index.js
|
L componentsフォルダ- App.js
App.jsに書かれているJSXはHTMLに変換されブラウザに表示される。
Reactのコードを実際にブラウザに表示するには、
App.js以外にもindex.jsとindex.htmlファイルが必要になる。
App.jsとindex.jsの関係
(index.js)
ReactDOM.render(<App />, document.getElementById('root'));
index.js内で「ReactDOM.render(<App />, …」と書くことで、
App.jsのJSX(render内のreturn内)が、HTMLに変換される。
この書き方は定型文のようなものなので、これで書く。
index.jsとindex.htmlの関係
..., document.getElementById('id名'));
さらに「…, document.getElementById(‘id名’));」と書くことで、
変換されたHTMLがindex.htmlの指定したid名の要素内に挿入される。
今回は、id名rootを指定している。
最終的に、index.htmlの内容がブラウザに表示される。
(app.js)のreturn部分が、
(index.js)のReactDOM~(“root”));に行って
(index.html)の指定したid名(div id=”root”部分)に挿入される
全部合わせると↓
コード部分で言うと
(app.js)
return (
<div>
<h1>Hello World</h1>
</div>
);
------------↓------------
(index.js)
ReactDOM.render(<App />, document.getElementById('root')); ←追記する部分
------------↓------------
(index.html)
<body>
<div id="root"></div> ←追記する部分(id="root")
</body>
全部合わせると↓
(app.js)
import React from 'react';
class App extends React.Component {
render() {
return (
<div>
<h1>Hello World</h1>
<p>一緒にReactを学びましょう!</p>
</div>
);
}
}
export default App;
--
(index.js)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
--
(index.html)
<!DOCTYPE html>
<html>
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div> →Hello World
一緒にReactを学びましょう!
<script src="bundle.js"></script>
</body>
</html>
CSSをつけよう
CSSを読み込む・CSSを適用・クラス名を付ける
return (
<div>
<h1>Hello World</h1> ←タグ名はそのままCSS指定できるからいつもとおりでOK
<p className='text'>ようこそ</p> ←クラス名はJSXにCSS指定するにはclassNameで指定するとOK
</div>
);
ーーーーーーーーーーーー
(stylesheet.css)
h1 {
color: red;
}
.text{
color: blue;
}
例
(app.js)
import React from 'react';
class App extends React.Component {
render() {
return (
<div>
{/* h1タグにクラス名を追加してください */}
<h1 className='title'>Hello World</h1>
<p>一緒にReactを学びましょう!</p>
</div>
);
}
}
export default App;
------------↓------------
(index.js)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
------------↓------------
(index.html)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="stylesheet.css">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>
--
(stylesheet.css)
.title {
color: #e6855e;
background-color: #f3f372;
}
JSXは最終的にindex.htmlに挿入され、ブラウザに表示されます。
そのため、index.html内でstylesheet.cssを読み込むことで、
CSSを適用することができます。
JSXにcssを指定する際、HTMLと同様にタグ名を指定します。
また、JSXにクラス名をつける際、HTMLと書き方が違うため注意しましょう。
JSXでのクラス名は、「className=’クラス名’」とします。
コンポーネント
(Language.js)
import React from 'react'; ←①Reactをインポート
class Language extends React.Component { ←②React.Componentを継承するLanguageクラスを作成
render() {
return (
コンポーネントでパーツ化したい部分を記述
);
}
}
最終的な例
(Language.js)
import React from 'react';
class Language extends React.Component {
render() {
return (
<div className='language-item'>
<div className='language-name'>HTML & CSS</div>
<img className='language-image' src='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg' />
</div>
);
}
}
コンポーネントでパーツを作るには、
そもそもの前提として、そのパーツ用の.jsファイルを作成してそのクラスを作って準備していく!
例)各Languageカードをコンポーネントで作っていきたい時は、
Language.jsファイルを作って準備していく
コンポーネントは「部品」や「パーツ」という意味です。
Reactでは、見た目を機能ごとにコンポーネント化して、
コンポーネントを組み合わせることでWebサイトの見た目を作ります。
一度作れば何度でも使えます。表示を変えて使うにはこの後出るpropsも使うと可能に。
今回は、言語レッスンを表示しているコンポーネントを作ります。
分かりやすいようにLanguageという名前をつけます。
Languageコンポーネントを作成するために、構成を学んでいきましょう。
まず、①Reactをインポートします。そして、②React.Componentを継承す
るLanguageクラスを作成します。このクラスがコンポーネントとなります。
クラス名はコンポーネント名になります。
コンポーネントが表示される流れ
・表示の流れ
(Language.js) →JSXの状態 →(app.js) →JSXの状態 →(index.js) → HTMLの状態に変換して挿入される →(index.html)
・ファイル構造
Reactフォルダ- index.html
|
L srcフォルダ- index.js
|
L componentsフォルダ- App.js
L Language.js
LanguageコンポーネントをApp.jsで呼び出して表示させることで、
最終的にLanguageコンポーネントパーツがブラウザに表示されます。
コンポーネントの使用方法・準備
例題
(Language.js)
import React from 'react';
class Language extends React.Component {
render() {
return (
<div className='language-item'>
<div className='language-name'>HTML & CSS</div>
<img className='language-image' src='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg' />
</div>
);
}
}
export default Language; ←①
(app.js)
import React from 'react';
import Language from './Language'; ←②
class App extends React.Component {
render() {
return (
<div>
<h1>言語一覧</h1>
<div className="language">
<Language /> ←③
</div>
</div>
);
}
}
export default App;
LanguageコンポーネントをApp.jsに渡すには、
まず作成したコンポーネントをexportする必要があります。
(Language.js)
import React from 'react';
class Language extends React.Component {
~~
}
export default Language; ←①Languageコンポーネントをエクスポート
次に、App.js内でLanguageコンポーネントを受け取り・表示するには、
App.jsで下図の2つの手順を行う必要があります。
②コンポーネントをインポート
import Language from 'そのコンポーネントが記述されているファイルへのパス';
例
import Language from './Language';
③JSX内に<コンポーネント名/>と書く
例
<Language />
props
propsとは
コンポーネントパーツに他と別の表示させたい文字などがある時はpropsを使用すればOK!
App.jsからコンポーネントなどに渡すデータをprops(プロップス)といいます。
App.jsからそれぞれ表示させたいデータ(今回で言うと各言語の名前と画像)
をLanguageコンポーネントに渡すことによって、パーツ内の表示を部分的に変えることが可能になる!
propsの渡し方(今回は渡すだけで、表示は実際にまだ変わってないみんな同じ)
props名=値
例(app.js)
<Language
name='HTML & CSS'
image='○○.svg'
/>
例題
(app.js)
import React from 'react';
import Language from './Language';
class App extends React.Component {
render() {
return (
<div>
<h1>言語一覧</h1>
<div className='language'>
<Language
name='HTML & CSS'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg'
/>
<Language
name='JavaScript'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/es6.svg'
/>
<Language
name='React'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/react.svg'
/>
</div>
</div>
);
}
}
export default App;
propsは、「props名=値」という形で、コンポーネントを呼び出
す場所から渡します。
今回は、Languageコンポーネントにnameとimageという2つのprops
渡しています。
propsの取得(渡されたpropsを受取る。ついにブラウザ上の表示も変わる)
例
<div className='language-name'>{this.props.name} </div>
<img className='language-image' src={this.props.image}/>
(App.js)
import React from 'react';
import Language from './Language';
class App extends React.Component {
render() {
return (
<div>
<h1>言語一覧</h1>
<div className='language'>
<Language
name='HTML & CSS'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg'
/>
<Language
name='JavaScript'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/es6.svg'
/>
<Language
name='React'
image='https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/react.svg'
/>
</div>
</div>
);
}
}
export default App;
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
(Language.js)ue
import React from 'react';
class Language extends React.Component {
render() {
return (
<div className='language-item'>
<div className='language-name'>{this.props.name}</div>
<img
className='language-image'
src={this.props.image}
/>
</div>
);
}
}
export default Language;
this.props.props名と書くと、App.jsから渡されたprops値を取得できる。
取得したpropsを用いて、各言語の名前と画像が表示される!
this.propsと書くと、{props名: 値}となり、propsのオブジェクト自体を取得できる。(普段使わないけど値の確認時とかで確認にはいいかも)
map
render() {
const fruitList = ["りんご","ミカン","バナナ" ];
return (
<div>
{fruitList.map((fruitItem)=>{ ←①
return <p>{fruitItem}</p> ←②
})}
</div>
);
}
上図は、JSXをmapを用いて効率的に表示している例です。
①mapメソッドで配列fruitListの各要素に対して順に処理を行い、
②<p>タグで囲んで各要素を表示させます。
mapメソッドの戻り値はJSXなので、引数であるfruitItemは
中括弧{}で囲むことに注意しましょう。
(App.js)
const languageList = [
{
name: 'HTML & CSS',
image: '○○.png'
},
{
name: 'JavaScript',
image: '△△.png'
}
];
return (
<div>
{languageList.map((languageItem) => {
return (
<Language
name={languageItem.name}
image={languageItem.image}
/>
~~
Languageコンポーネントをpropsで表示してみると
例題
(App.js)
import React from 'react';
import Language from './Language';
class App extends React.Component {
render() {
const languageList = [
{
name: 'HTML & CSS',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg'
},
{
name: 'JavaScript',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/es6.svg'
}
];
return (
<div>
<h1>言語一覧</h1>
<div className='language'>
{/* mapメソッドを用いて、Languageコンポーネントを表示 */}
{languageList.map((languageItem) => {
return (
// Languageコンポーネントを呼び出し、その中でpropsを渡してください
<Language
name={languageItem.name}
image={languageItem.image}
/>
)
})}
</div>
</div>
);
}
}
export default App;
--
(ちなみにLanguage.jsは。map未使用時と変化なし?)
import React from 'react';
class Language extends React.Component {
render() {
return (
<div className='language-item'>
<div className='language-name'>{this.props.name}</div>
<img
className='language-image'
src={this.props.image}
/>
</div>
);
}
}
export default Language;
それぞれの情報(今回は言語ごとの情報)を持つlanguageList配列に対して、
上のようにmapメソッドを用いると、簡単に各言語のLanguageコンポ
ーネントを表示できます。
レッスンサイトを作ってみよう
(Lesson.js)
import React from 'react';
class Lesson extends React.Component {
render() {
return (
<div className='lesson-card'>
<div className='lesson-item'>
<p>{this.props.name}</p>
<img src={this.props.image} />
</div>
</div>
);
}
}
export default Lesson;
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
(Main.js)
import React from 'react';
import Lesson from './Lesson';
class Main extends React.Component {
render() {
const lessonList = [
{
name: 'HTML & CSS',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/html.svg',
introduction: 'WEBページはHTML、CSSという言語によってその見た目が作られています。 実際にWEBページを作りながら学んでみましょう!'
},
{
name: 'Sass',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/sass.svg',
introduction: 'SassはCSSをより便利に効率的にするための言語です。',
},
{
name: 'JavaScript',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/es6.svg',
introduction: 'JavaScriptはフロントエンドだけでなく、サーバーサイドまで広い可能性を持つプログラミング言語です。',
},
{
name: 'React',
image: 'https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/react/react.svg',
introduction: 'ReactはHTMLのように、サイトの見た目をつくることができるJavaScriptのライブラリです。',
},
];
return (
<div className='main-wrapper'>
<div className='main'>
<div className='copy-container'>
<h1>Hello, World.</h1>
<h2>プログラミングの世界へようこそ!</h2>
</div>
<div className='lesson-container'>
<h3 className='section-title'>学べるレッスン</h3>
{/* lessonListに対して、mapメソッドを用いてください */}
{lessonList.map((lessonItem) => {
return (
<Lesson
name={lessonItem.name}
image={lessonItem.image}
/>
);
})}
</div>
</div>
</div>
);
}
}
export default Main;
上で、各レッスンカードを作成してサイトに表示させた状態になる。
モーダル
モーダルとは、ポップアップの様な、クリック時などに画面の前面に表示されるもの。
モーダルに表示させるものを準備
モーダル表示非表示
(Lesson.js)
constructor(props) {
super(props);
// stateの初期値をfalseで定義してデフォは隠しておく
this.state = {isModalOpen: false};
}
モーダルは、クリックによって表示/非表示が切り替わります。そこでモーダルが表示されているかそうでないかという情報をstateにしましょう。
isModalOpenという真偽値型のstateを用意し、trueなら表示、falseなら非表示になるようにします。
stateは、constructorで定義します。
今回、初期状態でモーダルは非表示にしたいので、「isModalOpen」の初期値をfalseにします。
「isModalOpen」がtrueのときはモーダルのJSXが存在し、falseのときは存在しないようにすれば、表示・非表示を切り替えることができます。
モーダル準備(表示するモーダルを入れておく変数)
render() {
// ①変数modalを定義
let modal;
// ②条件分岐のif文を用意してください
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>
);
}
モーダルには変数を利用していきます。
①モーダルを代入する変数を定義して箱を準備。
モーダルのJSXを変数に代入して表示していきましょう。
②①で準備した変数modalへ文書を代入するところで条件分岐を行えば、
isModalOpenがtrueのときだけモーダル用に準備してあるJSXが代入され表示されます。
③変数へ代入するJSXが複数行の場合、JSXを()で囲みます。
④変数に代入しておいたJSXは{変数名}で表示することができます。
全部合してみると
((Lesson.js)
import React from 'react';
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}
render() {
// 変数modalを定義
let modal;
// if文を用意
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>
);
}
}
export default Lesson;
モーダル表示(クリック時)
//①handleClickLessonメソッドを定義
handleClickLesson(){
this.setState({isModalOpen: true});
}
〜〜
//②onClickイベントを追加
onClick={() => {this.handleClickLesson()}}
上図の手順でレッスンカードをクリックしたときに、モーダルを表示できるようにします。
①デフォで非表示(false)にしているモーダルを、自分クリック時に表示(true)させるhandleClickLessonメソッドを定義。
②クリックされたら、handleClickLessonを実行する。
全体としては
(Lesson.js)
import React from 'react';
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}
// handleClickLessonメソッドを定義してください
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'>
{/* onClickイベントを追加してください */}
<div
className='lesson-item'
onClick={() => {this.handleClickLesson()}}
>
<p>{this.props.name}</p>
<img src={this.props.image} />
</div>
{modal}
</div>
);
}
}
export default Lesson;
モーダル非表示(モーダル内閉じるボタンクリック時)
// handleClickCloseメソッドを定義
handleClickClose() {
this.setState({isModalOpen: false});
}
〜〜
// onClickイベントを追加
<button className='modal-close-btn' onClick={() => {this.handleClickClose()}}>
とじる
</button>
上図の手順で、「とじる」ボタンをクリックしたときに、モーダルが閉じるようにします。
①モーダルを、自分クリック時に非表示(false)させるhandleClickClose()メソッドを定義。
②クリックされたら、handleClickCloseを実行する。
全字合わせると
(Lesson.js)
import React from 'react';
class Lesson extends React.Component {
constructor(props) {
super(props);
this.state = {isModalOpen: false};
}
handleClickLesson() {
this.setState({isModalOpen: true});
}
// handleClickCloseメソッドを定義
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>
{/* onClickイベントを追加 */}
<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>
);
}
}
export default Lesson;
応用:家計簿アプリ
Node.jsインストール
ReactではNode.jsが必要!
ブラウザで「Node.js Mac」を検索>Nodeのサイト>ダウンロードページ>LTS>Macアイコン>保存先指定>Nextを押していき完了させる。(もしくはここからダウンロード)
LTSは安定版だから良い!
インストールされたか確認
ターミナルを開く>「node -v」入力、「npm -v」入力>どちらもバージョン情報が表示されたらOK
WindowsPCの場合は、コマンドプロンプト開いて入力(エラーなったら管理者権限で開いて入力!)
プロジェクト作成
ターミナル開く>「D>works」に「kakeibo」プロジェクトを作成するとして下記入力していく
「cd works」>「npx create-react-app kakeibo –template typescript」
プロジェクト起動
「kakeibo」をVSコードで開く
タイプスクリプトを導入したREACTファイルには、拡張子「.jsx」ではなく「.tsx」がある
「ctr+j」でVS上でターミナル開く>「npm start」入力>自動的にブラウザで下記React画面開かれたらOK
便利な拡張機能(VS編)
VSの拡張機能アイコン>「react」で検索>下記を追加
これは「.tsx」ファイル作成時、記述部分に「rafce」入力・エンターでreactファイルの雛形を自動記述してくれたりなる
これは各ファイルの頭に拡張子のアイコンが付く
便利な拡張機能(Chrome編)
ブラウザで「Googleウェブストア」にアクセス>「react」検索>下記追加
これは、Chrome上でreactアプリを起動している時、右クリック>検証で右上のタブ欄に「components」が追加される。
そこから、コンポーネントやstateを確認しやすくなる。
不要なファイル・記述を消していく
下記ファイルは不要なため削除
下記記述は不要なため削除
プロジェクト作業開始
「kakeibo」をVSコードで開く
「ctr+j」でVS上でターミナル開く>「npm start」入力(上記削除したためreact画面は真っ白な状態)
URLのルーティング設定
reactルーターインストール
VS上でターミナルがstartした状態にしておいて、VSターミナルをもう一つ表示>「npm i react-router-dom」入力。 (ここからコピーする)
確認:「package.json」ファイルを開く>コード内に「react-router-dom」があるか検索>あればOK
コード記述
(App.tsx)
下記削除
ルート準備
return内(8行目あたり)に<Router>と記述またはその変換で出てくるものでエンターすると、
4行目みたいなのが追加される(変換で少し違うの出しても、結局は8行目がRouterなればOK。また4行目はRouterではなく、BrowserRouter as Routerと書き直す)
Router内(9〜11行目)に<Routes>と<Route />を追加。
4行目のas以降にもRoutes, Routeを追加。(画像は足りてないけど左記載のそれぞれ追加する)
ルートのパス(URL)指定・各サイトページ作成
<Routes>内の<Route>を追記する。
“/”はトップページ(reactの画像が表示されていた様なページ)、”/report”はトップページ直下のreportページへのURLを設定する。
element以降にある<Home />とかはコンポーネントを意味しているよ!
この後にそのコンポーネントのファイルを作成して中身作るよ!
srcファイル内に「pages」ファイルを作成し、「Home.tsx」「Report.tsx」を作成する。
コード部分には「rafce」と入力してエンターすると、雛形が自動記述される。
各ファイルのreturn内に書かれたのもがサイトに表示される。
作った各コンポーネントファイル(各サイトページ)をApp.tsxへインポート
上記でやった10.11行目のpathのコードで、element以降のコンポーネント名を反映させるため、
最後の一文字を消して入力してエンターでimportコードが自動記述される(Reportは2つあったら2個目使用)
確認:ブラウザでreactであったページ開いて確認、そのしたの/reportページも検索して表示されているか確認
14行目に”*”で12.13行目の様にパスを指定したもの以外のURLを検索された時に表示させるパスを作っておく
さっきと同じ様にインポートもさせる。でブラウザで末尾URLを適当に検索したらそのページ出る。
各コンポーネントに共通レイアウトのコンポーネント作成
サイドバーやヘッダーは各ページ共通のレイアウト。これを作成して設定する
共通レイアウトのルートを記述する
各コンポーネントファイルにも共有するものなので、各ファイルを囲った上の階層に追記。
パスは”/”で、コンポーネント名はAppLayoutとする。
14行目は同じく”/”だが、上の階層に”/”をしたことにより、子の”/”はindexとなる。
“/”でAppLayoutが呼ばれた時に子のindexであるHomeが呼ばれることになる!
レイアウト用のファイルを準備
src内に「components」フォルダ作成し、その中に「layout」フォルダを作成。
その中に「AppLayout.tsx」ファイルを作成。
rafceで雛形記述してテキスト何か書いて、App.tsxで異文字消して入力してエンターしてインポートさせる。
この今の状態だとどのコンポーネントページでもAppLayoutのみ映っている
子のコンポーネントファイルも表示させるには
レイアウトのコンポーネントで囲んだ、子たちのコンポーネントサイトも一緒に表示させるには、
親となったAppLayoutファイルに<Outlet>記述する。(今回9行目)
そしてimportもさせる。(今回2行目)
共通レイアウトのデザインをする!
MUIインストール
ブラウザで「MUI」アクセス>「Discover The Core Libraries」>「Material UI」>「Get Started」>「Installation」>下記Default instalation内のコマンドをコピー>下記VSコードのターミナルにペースト
MUIのアイコン類インストール
MUIサイトの上記Default instalation画面でスクロールし、「Icons」のコマンドをコピー>上記と同様に、VSコード上のターミナルへペースト
これにより、MUIサイト上で検索欄に「icon」で検索して出てくるアイコンたちを使用可能になる。
ドロワー準備
MUI上の検索欄に「Drawer」>「Responsive drawer」部分までスクロール>コードを表示させてコピー
今回使用する「Responsive drawer」は、レスポンシブもドロワーも付いているコード。
VSコード上で「AppLayout」ファイル開く>中身全て消す>さっきのコードをペースト>ブラウザで画面を確認すると反映されている。
Drawer内のコンテンツ部分を編集
サイトに反映させたMUIのDrawerコンポーネント内を編集します。
AppLayout.jsコード内の<Typography>がデフォでは中身部分になっているので、そこを削除。(<Toolbar />と</Box>内がメインのコンテンツ部分になっている)
各ページ用に準備したコンポーネントたちをコンテンツ部分に表示させるため<Outlet />を追記。
ここまででMUIのDrawerと各ページ用に作成したコンポーネントたちが併せてページに表示された。
Drawer内各コード確認
MUIサイトから「AppLayout.tsx」に貼ったDrawerコンポーネントのコードを見ていく。
不要部分削除
一旦ブラウザのページ画面確認する。見た目は変化なしでOK。
コード確認
return内:ページ表示全体
ページに表示される全て
AppBar(70~91行):ヘッダー
「AppBar」とすると、HTMLのヘッダーと同じ要素になる。
中には<Toolbar>があり、<IconButton~~>やタイポグラフィがある。
・<IconButton~~>:ハンバーガーメニュー部分のアイコンボタン
<MenuIcon />(85行目)のMUIから取ったメニューアイコンのコンポーネントを<IconButton~~>で囲むことで、<MenuIcon />のアイコンをbutton要素として扱えるようにしてある。
・<Typography>:ヘッダーに表示する文字
Box(94~123行):サイドバー
中には<Drawer>があり、モバイル用のとPC用のがある。
ドロワー:クリック時などに横から?表示される引き出し部分。
<Drawer>:モバイル用
sx(108行):ブレイクポイントサイズ
・sx:HTMLで言うstyle属性の様なもの。MUIでインラインでcssを当てるには「sx」と記述する。
その中にあるdisplayの「xs」「sm」はMUIのブレイクポイントを指している。
xs:画面サイズ0ピクセル以上の時の指定。
sm:画面サイズ600ピクセル以上の時の指定。
(例:下記だと、画面サイズが0ピクセル以上の時はdisplay:blockでドロワー表示される指定、600ピクセル以上の時はdisplay:noneでドロワー非表示となる指定)
variant(101行):表示設定:トリガーによる表示非表示
「variant=”temporary”」で、クリックなどをトリガーとしてドロワーを表示非表示可能にしている。
{drawer}(112行目):
32~60行目で作成しておいたdrawer定数を呼んでいる。
中には2つの<List>があり、ドロワー内の項目を準備・表示させている。
map関数でリスト内項目を順に表示させている。
(コード上段の<Divider />はただの区切っている境界線)
ドロワーが表示非表示される仕組みの設定
「onClose」(103行)として「handleDrawerToggle」という関数を呼び出している。
「handleDrawerToggle」関数は28行目で準備されている部分。
「setMobileOpen」として「mobileOpen」というstateを、TrueであればFalse、FalseであればTrueに切り替える設定。
「mobileOpen」は26行目で準備されている。初期値(右側の部分)はFalse。そしてこの「mobileOpen」というstateは先ほどのモバイル用ドロワーの「open」というプロパティで使用されている。この「mobileOpen」がTrueの時にはモバイル用のドロワーを表示し、Falseの時には非表示にさせている設定となってさせている。
ちなみにドロワーはハンバーガーメニュー部分のアイコンを押しても表示されるので、ヘッダー内82行目にも「handleDrawerToggle」関数は呼ばれている!
<Drawer>:PC用
variant(117行):表示設定:常に固定表示
「variant=”permanent”」で、ドロワーを常に固定表示(表示非表示切り替わらない)にしている。
sx(118行):ブレイクポイントサイズ
xs:画面サイズ0ピクセル以上の時の指定。
sm:画面サイズ600ピクセル以上の時の指定。
上記モバイル用とは逆に、画面サイズが0ピクセル以上の時はdisplay:noneでドロワー非表示状態の指定。600ピクセル以上になったらドロワー表示させる指定。
Box(129~135 行):メインコンテンツ
中には<Toolbar />と<Outlet />がある。
<Toolbar />:ヘッダーとメインコンテンツ間の微妙な余白部分がこれだと考えてOK。
<Outlet />:事前に別ファイルで作成していた「Home.tsx」や「Report.tsx」などの、ページになる各コンポーネントをこれで呼び出している。
コンテンツ背景色を変更(今回はMUI使用)
ブラウザで「MUI Color」検索>
下にスクロールし、好きな色を見つける
「AppLayout.tsx」のBox内に記述していく。
「bgcolor」で指定する。(下記どちらの方法で指定してもOK!)
もし色が反映されなかったら、左下にしてたターミナルでサーバーを起動しなおそう!(npm start)
ドロワーパフォーマンス向上?
いつのまにか104〜106に「ModalProps」「keepMounted: true」が記述されてある。(元から?)
これによりさらにモバイル用のドロワーの開閉がスムーズになっているみたい。
画面の高さに合わせて色も設定する
今の状態では部分的(高さが一部)にしか色反映されていない。
全体を囲んでいるBoxコンポーネントを画面高さに合わせることで解決させる。
お尻の部分に「minHeight: “100vh”」を追記する。高さが画面高さに変わるので、色反映の高さも一致する!
MUIコンポーネント名を変更
MUIから取ってきたコンポーネントの名前記述(26行)を変更しておく。
↓
MUIから取得したコードを機能毎に別ファイルに分ける
サイドバー別ファイルへ
AppLayout内のサイドバー部分(94〜126行)を丸ごと切り取る。
『src>components内に「common」フォルダ作成し、その中に「SideBar.tsx」ファイルを作成。
「SideBar.tsx」でrafceで雛形自動作成し、return内を消し、さっきのサイドバー部分をペースト。
切り取ったMUIコンポーネントをインポート
別ファイルに切り取ったMUIから取得していたコードで使用しているコンポーネントを、そのファイルへインポートしてあげる。
今回はBoxとDrawerだけだったので、最後の一文字を消してまた一文字入力してインポート反映させてあげる。
下記1行目にインポートが追加された。(されなかったら手動でもいいかも)
また、return直下のコメント?(6行目はこれだエラーなるらしいから削除しておく)
切り取った元の部分に呼び出し設定をする
「AppLayout.tsx」→「SideBar.tsx」にSideBar部分のコンポーネントを移したので、移し元部分に移し先のSideBarを呼べる様に設定を記述する。<SideBar />で呼び出せる。
importは自動でされなかったので手動で記述する。
from以降は実際のSideBarのアドレスで書く。
勉強
事前準備
Node.jsインストール
reactを使用するには「Node.js」をインストールする必要がある
reactに「Node.js」が必要な理由は?
・ローカルサーバーの起動、
・ライブラリの管理などに「Node.js」が関連しているため!
Nodeサイトへアクセス>自分のPCに適したものを選択>ダウンロード
確認:ターミナル開く>入力「node -v」>バージョン表示されたらインストール完了済!
yarnインストール
yarnは、パッケージマネージャーと呼ばれているもの。
yarnではなくnpmを使っていっても問題ない!
yarnをインストールする理由は?
・ライブラリのインストール、
・バージョン管理などをしてくれるため!
ターミナル開く>入力「npm install -g yarn」>入力「yarn -v」バージョン表示されたらインストール完了済!
VSコードインストール
ブラウザで「VSコード インストール」検索>インストール
VSコード便利な拡張機能
ES7~:react特有のコードを自動変換や自動表記してくれる!
Auto Close~:HTMLを書いた時、閉じタグを自動で追記してくれる!
Auto Rename~:HTMLの開始タグを変更時、閉じタグも一緒に変更してくれる!
Prettier~:コードのインデントがぐちゃぐちゃでも、
保存時に見やすく整えてくれる!
Prettierを使用する設定
Prettierインストール後下記設定もすると使用可能になる。
・「Command+Shift+p」入力>枠に「setting」入力>「基本設定:ユーザー設定を開く」>中央欄に「format on save」入力>下の「Editor: Format On Save」に✅する!
Mithril Emmet:HTMLを略して書ける。
(例:リストを5つ書く時→「ul>li*5」で作れたりもする!)
このサイトから略一覧を見れるよ!
VSコード自体の便利な設定:
・「Command+Shift+p」入力>枠に「固定スクロール」入力>「表示:エディター固定スクロールの切り替え」をクリック
今どの階層内のコードを見ているかを上部に親階層のコードをちらっと固定表示させてくれる!
階層(ネスト)が深くなった時に便利!
VSコード以外の便利なもの
cheet sheet
「command」長押しで、開いているソフトのショートカットを表示してくれるよ!
ブラウザで「cheet sheet」検索(MacならMacの調べる)>ダウンロード
diff checker
2つの文内から異なる部分を見つけられる!
左枠と右枠に何か入力>下部にある「Find difference」>異なる部分が分かる。
codic
日本文字を、クラスや関数名などでよくプログラムで使われがちな名前(英語)に変換してくれる!
左側に日本を入力>右側によくコードで使用される英語の名前に変換をしてくれる。
DeepL
文章を翻訳してくれるよ!
左側に言語ペーストや入力すれば、右側に精度の高い日本語にしてくれる。
DeepLとChromeの拡張機能使うともっと便利!
ChromeでDeepLの拡張機能をインストールすると、サイトで翻訳したい文章を選択>DeepLアイコンクリック>日本語訳が表示される。
図鑑アプリ作成(API取得、ページネーション学習)
プロジェクト作成
ターミナル開く>好きなディレクトリに移動させる>入力「npx create-react-app naruto-app」>VSコードでそのファイル開く>ターミナル「yarn start」>reactのローカルサーバー立ち上がる(ブラウザ表示される)
不要ファイル削除
不要コード削除
index.js:5:import~
14~17:コメントと最終行
App.js:1:import~
7~20:header部分(代わりにHello Worldとか記入しておく)
css
App.cssにここからApp.cssのコード取ってきてコピペする
(サイトへ行く)
サイトアクセス>「Get All Characters」>JSONふぁいるのつづきやってもいい(セクション3の9最後らへん)
API
Axios(アクシオス)インストール
Axios:reactやvueなどのJavaScriptのプロジェクトでAPIを叩く時に非常によく使われるライブラリ!
プロジェクト内ターミナル>入力「yarn add axios」
APIからキャラクターのデータ取得する
App.js内に記述していく!
useEffectを使用する
今回APIを叩くのは”ページ表示の一度だけ”でOKのため、
useEffectを使用(5行目)
第2引数に空の配列を指定する。それにより、第1引数に入っている処理がコンポーネントのマウント時に呼ばれて、ページの表示時に1度だけ処理を走らせることができる様になる。
追加:1,5
APIを使用するためのURLをサイトから準備
追加:7,9「;」
7意味:今回はキャラクター情報をAPIで取ってくるので、「fetchCharacters」定数をしてみる。
今回はAPIを叩いてデータが返ってくるのを待ってから行う処理があるため、「async」を付けて非同期関数にしておく!
対象となるAPIのURLが必要なので、サイトから探す>URLをコピー
追加:8:関数 apiUrl(APIのURLの関数)を準備し、対象となる使用するURLを格納して準備する
Axiosを使用してサイトのAPIを叩く部分を作成
追加:11,12
関数:result(apiUrlから返ってきたデータを格納する関数)を準備
11意味:Axiosのgetメソッドを使用してapiUrlにリクエストを送る。awaitでデータが返ってくるまで待って、返ってきたデータをresultの定数に格納している。
12:ここで一旦、resultの中身を確認したいのでコンソールログしてみる。
追加(自動1)(1:11でaxios使用したから自動で1のimport axiosが追記されている。)
追加:7:useEffectの第1引数で、上記の、APIからデータ取得するため準備したまとまりのfetchCharactersを呼んであげる。
確認:ブラウザでAPI繋がったか(APIからデータ取得されたか)見てみる
VSコード下部でターミナル2つ目開く>ローカルサーバ(デフォがreact画面のlocalhost3000)を立ち上げるため入力「yarn start」>コンソールログに表示させただけなので、ページで右クリ>検証>Consoleタグ>中身展開して配列でAPIデータ(キャラ名、画像などの情報)が取れていればOK!
検証画面にObject2つあるのは仕様のため気にしなくていい!
取得したAPIデータを、コンソールではなくブラウザ上で表示させる
APIから取得したデータをステートに格納
useStateを使用してみよう
useState
追加:6
6意味:useStateを使用して、charactersというステートを作成。
charactersに後ほど値をセットして更新するsetCharacters関数。
charactersの初期値は、useStateの引数にある空の配列が入っている。
fetchCharacters内でsetCharactersを使用し、APIから返ってきた全データの中から必要なキャラクターデータを抜粋してセットする
今回のAPIではdata>charactersに配列としてキャラクターのAPIデータが入っている。
追加15
15意味:取得したAPIの全データ(result(APIから返ってきたデータを格納した定数(14行))のうち今回使用するのはキャラクターデータ部分(data>characters)のため、
setCharactersメソッドには、全APIデータ>data>charactersのAPIデータを抜粋して格納している!
上記のこのsetCharactersに格納したAPIデータたちが新しい更新値として結果的に6行目のcharactersに格納される!
これでステートの中にAPIデータが入る様になった!!
ブラウザで取得した画像を表示
削除20(今入れてあるreturn内は仮なので一旦消す)
追加20〜36
23意味:上記で準備したAPIデータが入ったcharactersを、map関数で回してデータを一件一件character変数に格納している。各データにしたものを直下のreturn内で使用していく!
25意味:imgのkeyは、各データ重複しないユニークになっているデータを軸にする。ブラウザの検証で位置を確認。
27意味:今回は画像は各データに1つずつ表示させるから、[0]のみ指定している。
’useState’ is not defined.のエラーなるので入力「import React, { useState } from ‘react’;」
画像が無いなどの時のために(さんこうえんざんしを使用する)
「さんこうえんざんし」
条件(29行)がtrueであれば、「?」を実行、falseであれば「:」を実行。
追加29〜31(修正:27)
29〜31意味:1つ目の画像がnullでなければ(存在すれば)、
1つ目の画像を表示し、
無ければダミー画像を表示
他のデータも表示していく
imgの次にその他情報(キャラ名、登場作品、所属)も追記していく
追加37〜49
39、42、46でAPIデータを表示するための{}を記入。(ブラウザの検証で階層確認して書く)
エラー(Cannot read properties of undefined (reading ‘appearsIn’))対応
表示しようとしたが下記エラーなった。
エラー意味:appearsInが読み込めない:
これは各データによってはappearsInの上階層のdebutが無いものがあるため。の意味
エラー解決法:「さんこうえんざんし」を使用し、データが無い場合、ある場合によって指定する。
修正42
↓さんこうえんざんしにする
また、さんこうえんざんしは略すとこう書ける↓
?の左条件(character>debut)が
存在する場合(nullでない場合):? の右側を表示
存在しない場合(nullの場合) :??の右側を表示。
修正46
その下にあるaffiliationも同じ様にさんこうえんざんしで条件で表示させ、まとめるとこう
削除17
使用するAPIデータ取れてるのでコンソールログ消しても良い。
次ページ以降もデータを表示
次ボタンクリック時、2ページ目以降のデータも取得させてみる(fetchCharactersを使用)
現在のページデータ格納用のstateを作る
追加8
8意味:まずは現在のページデータを格納する用のステート「page」を作る。
最初に開いているページは1なので、useStateの初期値は「1」にする。
次ページ分のデータを取得する処理を準備
追加21~25
21~25:次ページのデータを取得させるための「handleNext」という式を準備。
22:「nextPage」という定数を準備(上記準備した「page」ステート(現在ページのデータ)に+1したもの)
23:awaitさせてfetchCharactersを呼び出すが、次ページのデータを取得したいので引数にはさっき準備したnextPageを指定する。
24:次ページを開いたのが現在のページになるので、setPageに引数nextPageを指定し、「page」ステートの中身を更新させておく。
次ボタンに、次ページデータを取得させる処理を付ける
次ボタンに上記準備した「handleNext」処理を付けよう!!
追加63〜67
前後ボタンを作成する。
66意味:ボタンクリック時に「handleNext」を呼び出す。
65意味:ページ番号は、現在のページを格納する「page」ステートを作ったので、それを指定することにより、動的にそのページ数を表示させることが可能になった!
???
次ボタンクリックしてみたけどページ数は変わるけどデータが変わらない。いつの間にか下記コード増えてた。14、16を修正したら更新された。いつどこで。。?とりあえず追記した。
前ページも表示させる
追加27〜31
27〜31:ほぼhandleNextと変わらないので、それをコピペして「handlePrev」とする。
名前をhandlePrevやprevPageなどに修正する。
28:page -1にする。
修正70
70:前ボタンクリック時にhandlePrevの処理をさせるため、onClick={}をボタン内に準備
1ページより前・最後ページより後に行かない様、ボタンにクリック不可の条件を付ける
前ボタンを、1より前に行かせない処理
修正70
70意味:disabled={page === 1}で、1ページ目の時に前ボタンを機能させない指定。
表示件数の指定をAPIサイト上で調べる
APIドキュメントを確認して、表示数の情報を調べる
URL最後の「limit=20」で下記が分かった!
・1ページに20件ずつ表示させていること
・limitで表示数を指定していること
コード上で自サイトでの表示数を変えてみる
追加6
ドキュメントを見てlimitというもので1ページ20件を表示数指定していると分かったので、
今度は自分でlimitという定数を作り、表示数を800としてみる。(800件/1ページ表示)
ファイル内どこでもこの表示数の情報を使用したくなるかもなので、関数内とかではなくApp外に置いておいてみる。
修正18
18意味:実際にAPIデータをページごとに取得してきているのはfetchCharactersのaxiosのgetなのでそこにlmitで指定した件数分のデータ取得・表示させるためAxiosの第2引数にも「limit」追記指定。
上2つの指定でページ表示数が変わった!!
次ボタンを、最後ページより後に行かない処理
最後ページは、imitで指定した表示数(例えば800)よりも取得したデータ数が少なくなる(はず)。その場合に次ボタンを機能させない様にする。(ぴったしの場合もあるが今回はそこ考えることはなし。。)
修正74
74意味:limitよりも現在ページで取得したキャラクターデータ数(ブラウザ検証コンソールで調べるとcharacters>lengthが現在ページの表示数みたい)が少なければ、「disabled」がtrueになってボタン機能させない指定!
ローディング表示
ローディング用さんこうえんざんしを準備
追加11
11意味:「isLoading」というローディング用のステートを作成。ブーリアン型。初期値はfalse。
APIを叩いてデータ取得する直前にtrueにしてローディング表示、
取得後はfalseにして非表示!な仕組み。
ローディング表示タイミングを準備
追記19,22
19:APIを叩く直前にsetLoadingをtrue(表示)
22:叩いて取得したデータをstateにセットし終わった後にfalse(非表示)
ローディングの表示場所を準備
追加39
39:表示させる為return内に書く。
さんこうえんざんしで、isLoadingがtrueの時、「?と:」の間が実行される。
isLoadingがfalseの時、「:と}」の間が実行される。「:と}」の間で色々表示させたいので、下記39行最後の「}」はmainが終わる67行に置く。
↓
これでローディング表示後にmain内が表示される様になった!
ローディング表示を見てみる。(わざとロード速度の遅い状況を再現して確認)
Chromeの検証ツールではブラウザのネットワーク速度を遅い環境を再現する機能がある。それを使ってみる。
ブラウザ右クリ>検証(デベロッパーツール)>Networkタブ>少し下にある🛜マーククリック>ツール下の方にNetwork conditions内にNetwork throttlingNetwork throttlingが表示される>「slow 3G」を選択でOK!
これは、回線の悪い状況でWebがどう表示されるかを確認するためにフロントエンドのひとが使ったりするから覚えておこう!
したければヘッダーを修正
音楽プレイヤーアプリ
プロジェクト作成
ターミナル開く>好きな階層で入力「npx create-react-app music-app」
ローカルサーバを立ち上げる
ターミナル開く>作成したプロジェクトへ移動「cd music-app」>
ここでローカルサーバ立ち上げ「yarn start」>react画面なればOK
不要ファイル・コード削除
不要ファイル削除
不要コード削除
index.js:5行目のimportと下記
App,js:1、2行目のimportと下記header部分(削除後にhello worldとか書いておく)
↓
確認:ブラウザ表示してhello worldがエラーなく表示されていたらOK!!
tailwindcss
tailwindcssはcssフレームワークの1つ。
tailwindcssインポート後に何が出来るかと言うと、、、
特定のclass名をHTMLへ書くと、tailwindで準備されている綺麗でオシャンなcssデザインを使える様になる!
tailwind playで試すこともできる。
app.js結局全部消してこちらコピペする。
一旦下記だけ表示されればOK .
tailwindcssセットアップ
VSコード上の下部でターミナル開く>入力「yarn add -D tailwindcss」
VSコードの一番上の階層に新規ファイル作成(名はtailwind.config.js)
tailwindcss createサイトを開き、サイトの3番目のコードを上記ファイルにコピペ
次に、index.css内コードを全て消し、下記入力
ターミナル>入力「yarn start」>ブラウザで下記なれば反映OK!
APIにHTTHTTPリクエストをするので「axios」インストールしておく
VSのターミナル>「yarn add axios」
Spotify APIのセットアップ
Spotifyアプリ(Client ID, Client Secret)作成
Spotify APIサイトにアクセス>1のdashboard(下記画面にならなければspotifyにログインしてからアクセスする
>createクリック
下記の様に入力していく
最後に同意の✅>SAVE>下記画面なればアプリの作成完了!
画面右上の「Settings」からアプリのClient IDやClient secretなどが確認できる!
Client secretがない時は、もっとみる的なボタンがあるからクリックする
Spotify APIのアクセストークンの取得
アクセストークンとは
cliantID/secretを使用し、APIを叩く際に認証に使うランダムな英数字。
トークン取得後1時間しか使用できないためセキュリティ的に強い。
アクセストークン取得のためのコード準備
環境変数を準備
環境変数とは
個人情報を守るもの。コード上にクライアントID/SECRETなど情報をそのまま入力すると、ソース公開などした時に見られて盗まれる場合がある。そうさせないためにソース上から切り離すため使用される。
「.env」ファイル作成
reactでは「.env」ファイル内で環境変数の宣言をする!
一番上の階層にファイル作成(名は「.env」)>サイトから情報をコピーして下記記述
reactでは各頭に「REACT_APP_ 」を付けないと環境変数として認識されない。
「.env」ファイルを隠す
「.env」をgitの管理下から外させたいので、「.gitignore」開く>「.env」を分かりやすい位置に入力
本番環境と開発環境で変えたい設定値などもここで管理することが多い!
確認(環境変数が認識されたかどうか)
(App.js)
追記2,3:App内でコンソールログする。
2,3意味:環境変数を指定するには「process.env.環境変数名」とする。
環境変数を入力・更新したら再度ローカルサーバーを立ち上げないといけない。
ターミナルで入力「yarn start」>ブラウザの検証>コンソールタブに表示されていればOK!
アクセストークン取得方法をAPIドキュメントで確認
コード
spotify用ファイル準備
src内にフォルダ作成(名は「lib」)>その中にファイル作成(名は「spotify.js」)
今後spotify関連の処理はここに追記していく!
アクセストークン取得の処理
axiosを使用してアクセストークンを取得する
(spotify.js)
追加1〜6
下記でaxiosを使用してPOSTリクエストを送れる。
APIドキュメントを確認しつつ取得コードを完成させる
修正4:第一引数にはAPIのURL。
追加5〜9:第二引数にはボディー。
追加10〜14:第三引数にはヘッダーを書いてみる。
追加17:取得処理がなっているかコンソールで確認
これで「response」の中にアクセストークンが入った!!
App.jsでSpotify.js内で準備した「getToken」を呼んでアクセストークンをページ上で取得できるか確認
(App.js)
削除2、3
↓追加2
「yarn start」してブラウザ検証コンソールでトークン取得できている!!!
「spotyfy.js」のファイル内を使いやすくしよう
spotify関連の処理がまとまった関数を作ったり、変数にアクセストークンを格納するなどして今後追加していくspotify関連の処理からもアクセストークン取得をしやすくなどしていこう!
クラス作成
追加3〜7:「SpotifyClient」クラス作成
追加4〜6:トークン取得してメンバ変数に入れる初期化用の処理「initialize」
切取り13〜24
「getToken」内の13〜24の処理を切り取る。
追加5〜16
5〜16意味:初期化用処理の「initialize」内に、「getToken」内で切取った中身をペーストする。
(アクセストークン取得までは前回準備した「getToken」と同じ処理のため)
削除21〜23:中身抜かれた「getToken」は「initialize」で中身使うからもう削除。
↓
追加18
18意味:「response」の中身をクラスのメンバ変数に格納していくので、まずはこちらのspotifyClientのインスタンスを作成して準備する。
アプリ(AIコードレビュー)
プロジェクト作成
ターミナル>好きなに移動して入力「npx create-react-app code-reviewer」
ローカルサーバを立ち上げる
ターミナル開く>作成したプロジェクトへ移動「cd code-reviewer」>
ここでローカルサーバ立ち上げ「yarn start」>react画面なればOK
不要箇所削除
(index.js)
削除:5、14〜17
(App.js)
削除1〜2,7~20(header削除した後は代わりにHello Worldなど入力しておく)
TailwindCSS
インストール
ターミナル>プロジェクト内で入力「yarn add -D tailwindcss」
セットアップ
フォルダ最上階層にファイル作成(名は「tailwind.config.js」)
準備記述(tailwind.config.js)
サイト(tailwindcss react install)>3のコードをコピー>「tailwind.config.js」にペースト
準備記述(index.css)
ここから「index.css」のコピペでコードに貼り付ける。
axios
API使用するためaxiosをインストール
ターミナル>プロジェクト内で入力「yarn add axios」
OpenAI API
APIキー取得
サイト>サインアップ>(API)>右上「Dashboard」>左バーから「API keys」
(このページでAPIキーの一覧を確認可能)
「create new secret key」>任意のアプリ名入力> create>表示されるキーをコピーしてメモしておく
APIキーでAPIを叩く
環境変数作成
最上階の階層に「.env」ファイル作成
追加1:上記コピーしたAPIキーを格納する
ターミナル>「yarn start」する(環境変数変更した後はローカルサーバ立ち上げなきゃ反映されないため)
API用ファイル作成
src>lib>openai.jsを作成して準備
追加1〜5:クラス作成(名はOpenaiClient)
追加2〜5:その中にコンストラクターで、メンバ変数(apiKey)に上記のAPIキーを格納する。
openaiClientをインスタンスにした時に、APIキーというメンバ変数に自動的に変数内のAPIキーが入ってくる形になる?
APIドキュメント(56番、AIにリクエストを投げてコードレビュー1の解説はあとでやろう)
ChatAPIのサイト>「Create chat completion」にあるAPI使い方を確認
(下の6は上の4と同じで行が違くなっただけ。編集でなんとかして)
axios使用
1:axios使用のためインポートを準備!
14意味:第一引数にAPIに書かれているURL
15意味:第二引数に先ほど準備したリクエストデータ
16~21意味:第三引数にヘッダー
26意味:OpenaiClientをインスタンス化してopenaiに。
27意味:エクスポートして外のファイルからも呼び出せるように準備!
細部
ここからApp.jsをコピペ>ローカルサーバー立ち上げてブラウザ確認>下記なればOK
ユーザー入力値、APIから返った値、を格納するステート準備
1意味:useStateを使用するためインポートして準備
4意味:ユーザー入力値を格納する「content」ステート
5意味:APIから返ったデータを格納する「result」ステート
15修正(16~18追加)
15~18意味:ユーザー入力値(テキストエリアの値)が変わるとこのonChangeが走って、都度テキストエリアの中身を「content」ステートにセット更新されていく仕組み。
画面の「レビューボタン」クリック時の処理を準備
messagesを準備
APIドキュメントで確認した、messagesという、ボディーに渡す内容を準備。
7:review関数を準備。
16:setResultで、APIから返ったAIの回答を「result」ステートにセットさせる。
2:openaiをインポートさせる。
上記準備したreviewメソッドをbuttonタグ内に準備!
AIへの指示をより的確にしてもらうため、promptに下記書く。サンドボックスってので調整もあり?
これは色々変えて遊べる部分かも!
22修正:コンテントを渡している部分を修正する。 先ほど準備したプロンプトとコンテンツを連結させて、AIのAPIの方に投げてあげる仕組みにする。
25修正:正しくはawait入れるらしい。
これでオープンAIを叩いて返ってきた値がresultになる。
52:resultを表示させるように準備。
ここまでで、ブラウザで入力してレビューボタン押してこんな感じなればOK!
どうしても429エラーなるのでChatGPTを有料課金して、$5分課金したら見事反映した!!!いえーい!
ローディング実装
17:ローディングのステート準備
20、29:API叩いて結果が返ってくる前後でローディング設置。
49,52(今書いてある「レビューする」は消しておく):また、API実行中とその後でボタンの表示を変える。ローディングも入れる。
57:結果画面を表示させる部分にも修正追加。({result}部分を下記に修正)
表示結果をマークダウン形式に
(「react-markdown」サイトにあるreact-markdownというライブラリを使用する)
サイトにある下記の使い方を参考にコード作る。(3行目にある様なimport Markdownしたり、画像の一番最後にある{markdown}みたいにしたりする)
ターミナル>入力「yarn add react-markdown」>「yarn start」>上記コードで57行だった{isLoading部分を、サイトの使い方を参考にmarkdown含めた下記の感じに修正する。
そして3の様にimportも忘れずに追記。
ちなみに、現在設定してあるindex.css内にはclassName=”markdown”にCSSのの指定をしているからそのまま画面はCSSデザインされる様にしてある。
結果は下記画面の様(タイトル太文字、背景グレーなど)になればOK!!完成!!
応用
自分的にはカウンセラーAPIを作ってみた!
↓↓☺️
厳しめの指示に変えると同じ文書でも返ってくる言葉を変えられる。