UdemyでReactを勉強する日記
frontend真面目にやったことないので基礎からちゃんとやる。
ref: https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/25595350#overview
現在地
あなたの現在地 by ChatGPT
おそらく知識としては
jQuery
↓
gulp/grunt
↓
Vueを少し触った
↓
React少し触った
↓
Next.jsのJSXを修正するくらい。
今のReact開発者の感覚だと
React
↓
State
↓
Hooks
↓
Router
↓
SSR
↓
SSG
↓
ISR
↓
Server Components
↓
Next.jsなので 途中がかなり抜けています。
ということです。
さ、やろう
Section 2
import & <script type="module"
jQuery時代にはなかったimport. Javascript fileからJavascript fileを呼び出せる。
流れは html -> (load) -> js1 <- (inject) js2 という感じ?
まず js2 をこうしておく
export function aaa(){
alert(1);
}
それをjs1で波カッコつけて読み込む。
import { aaa } from "./2.js";
// call
aaa();
importしてる方を HTMLで type="module" をつけて読み込むと使える。
x <script src="1.js"></script>
o <script src="1.js" type="module"></script>
昔ながらの type=module なしで読み込むと、importは使えない。
❌ Uncaught SyntaxError: Cannot use import statement outside a module (at app.js:1:1)
当時本当にこれ欲しかったな!!!
export default
export const password = "abc123";
export default "default-value";
default は波カッコなしで import する。
import thingamabob, { password } from "./topics.js";
^^^^^^^^^^^
console.log(password); // Output: abc123
console.log(thingamabob); // Output: default-value
波カッコを忘れると、defaultを読んでしまうので注意!!
import password from "./topics.js"; // default_valueが入ってる!!
as なしで自由に名前つけれる default は危険すぎると思う
objectとしてまとめてimport
import * as util from "./topics.js";
console.log(util.password); // Output: abc123
console.log(util.thingamabob); // Output: default-value
Destructuring
object: colonで名前がつけれる。
function: {} を引数のとこに入れるとobjectから取り出せる。
// list
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1 2 3
// object
const { name, age } = { name: 'Alice', age: 30 };
console.log(name, age); // Alice 30
// object with renaming
const { name: userName, age: userAge } = { name: 'Bob', age: 25 };
console.log(userName, userAge); // Bob 25
// function parameters
function greet({ name, age }) {
console.log(`Hello, my name is ${name} and I am ${age} years old.`);
}
greet({ name: 'Charlie', age: 35 }); // Hello, my name is Charlie and I am 35 years old.
Spreading
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // [1, 2, 3, 4, 5]
const obj1 = { name: 'Alice', age: 30 };
const obj2 = { ...obj1, city: 'New York' };
console.log(obj2); // { name: 'Alice', age: 30, city: 'New York' }
めちゃめちゃやばい JSX の import
画像もcssもimportできちゃう。めっちゃやばい。
import pngFile from "./assets/react-core-concepts.png";
import "./index2.css";
function App() {
return (
<div>
<img src={pngFile} alt="Stylized atom" />
この時の main jsはこう
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
const entryPoint = document.getElementById("root");
ReactDOM.createRoot(entryPoint).render(<App />);
こんなやばいことができるのはviteのおかげ。
はい、ざっくり言うと Vite は web server でもあり、transpiler 的な処理もするツールです。
JSX の変換などは主に esbuild や React plugin が担当します。なので Vite は「transpilerそのもの」というより、transpiler や bundler を束ねて、ブラウザに必要な形で返す開発サーバーという理解が近いです。
不思議な変換pluginが入ったweb serverという理解か
vite
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()]
});
viteには「React プロジェクトとして扱ってね」という最低限のヒントは入っています。あとは Vite 側がかなり賢く既定動作を持っています。
あまりに不思議なので別記事にした。
props.children
不思議なreserved word children を覚えた
function App() {
return (
<div>
<Card name="Card 1">
<menu>
<button>aaa</button>
<button>bbb</button>
</menu>
</Card>
</div>
);
この Card の中身のhtml tagをpropsで渡したい
function Card(props) {
return (
<div>
<h1>
{props.name}
</h1>
{props.children} // <--------------
</div>
)
}
props.children に不思議な力で入ってくる。
props を {} で渡す
こうやって渡すと propsをkeyで取り出せる
function Card({name, children}) {
return (
<div>
<h1>
{name}
</h1>
{children}
</div>
)
}
props に anonymous function を渡す
定義するのは無名関数なので、無名関数が実行された時には中の関数が実行されるので、 そっちの () が必要
function handleSelect(selectedButton) {
console.log(selectedButton);
}
function TabButton({ mySelectedFunc, children }) {
return (
<button onClick={mySelectedFunc}>
{children}
</button>
)
}
function App() {
return (
<menu>
<TabButton mySelectedFunc={() => handleSelect('aaa')}>AAA</TabButton>
<TabButton mySelectedFunc={() => handleSelect('bbb')}>BBB</TabButton>
<TabButton mySelectedFunc={() => handleSelect('ccc')}>CCC</TabButton>
</menu>
);
}
useState
ここからがreactだ!
use から始まるのは全部 React Hooks. useState とか全部 React Hooks!!
Hooksはcomponentの中でしか書けない!
component functionのtop levelにしか書けない!! (nexted functionはだめ)
# WRONG!!
---
const [] = useState(); <--- x
function App() {
---
function App() {
if ()
const [] = useState(); <--- x
---
# GOOD!!
function App() {
const [] = useState(); <------ o
...
}
hookの値が変わると、componentはre-renderingされる
/**
title = current value
setTitle = updater
'I lean on you' = defalut value
*/
const [title, setTitle] = useState('I lean on you');
import { useState } from "react";
const title = "React Essentials ddd";
function App() {
const [selectedTopic, setSelectedTopic] = useState('Please clidk a button');
function handleSelected(selectedButton) {
setSelectedTopic(selectedButton);
}
return (
<div>
<main>
<h2>Time to get started!</h2>
<menu>
<button onClick={() => handleSelected('Components')}>Components</button>
<button onClick={() => handleSelected('State')}>State</button>
<button onClick={() => handleSelected('Props')}>Props</button>
</menu>
<section>
<h3>{selectedTopic}</h3>
</section>
</main>
</div>
);
}
export default App;
jsx if shorthand
この2つは同じ意味
{!selectedTopic ? <p>Please select a topic to view its details.</p> : null}
{!selectedTopic && <p>Please select a topic to view its details.</p>}
{} のなかにjsxも書ける。() でくくる
{selectedTopic && (
<div id="tab-content">
<h3>{EXAMPLES[selectedTopic].title}</h3>
<p>{EXAMPLES[selectedTopic].description}</p>
<pre>{EXAMPLES[selectedTopic].code}</pre>
</div>
)}
jsx {}
これでも動く
{"hello"}
{["hello", "world"]}
{[<p>hello</p>, <p>world</p>]}
これは動かない
{hello}
変数helloがあれば動く
compoenent props の渡し方
こういうcomponentがあるとき
function CoreConcept({ image, title, description }) {
こういデータがあり
export const CORE_CONCEPTS = [
{
image: componentsImg,
title: 'Components',
description:
'The core UI building block - compose the user interface by combining multiple components.',
},
jsxはこう渡す
{CORE_CONCEPTS.map((item) => (
<CoreConcept {...item} key={item.title} />
))}
{...item} は展開されて image={item.image} title={item.title} description={item.description} と同じ意味になります。
、map() で配列を描画するときは key が必要です。React は key を使って要素の変更を効率的に追跡します。key は CoreConcept の props ではなく、React の内部用の識別子。ないとwarningが出る!
ここら辺で、useStateの値が変わった時にcomponentがre-renderingされる、つまり、js fileが上から下にもう一度読み込まれることに気づいた。これはでかい。child componentsも同様に読み込まれるから、getRandomInt()とかあると、それも実行されてrenderingされたりする。
されたくなかったら、変わるところをchild componentに分離する。親はレンダリングされないので、親から分離すれば、子供の世界だけレンダリングされる。
Fragment
root objectの代わり。vueの <> と同じぽい
return (
<Fragment>
<p>
<p>
</Fragment>
基礎からやろうとは思ったけど、まさか import から勉強したことなかったとはな。思い立って良かった。がんばろ。