| フレームワーク | 特徴 |
| AngularJS | MVCに対応したフルスタックフレームワーク.パフォーマンス面でReactとVue.jsに負けている |
| Vue.js | UIに特化したフレームワーク.Reactと比較すると少しパフォーマンス面で劣っている |
# プロジェクトの作成 % npx create-react-app プロジェクト名 # (対象ディレクトリに移動して)Reactプロジェクトの実行 % npm start
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();const name = "John";
const element = <h1>Hello, {name}</h1>;
// 変数と文字列を結合した場合は`{...}`内で行う
// 属性値を指定する場合は`"{...}"`のように囲わない
const profile = <img src={'https://profile/' + name + '.jpg' />;
const name = true;
const element = <h1>{name}</h1>;
// → <h1></h1>が描画されるlet elem = <p>Hello</p>;
if (!nameHidden) {
elem = <p>Hello, {name}</p>
}
return (
<h1>Welcome</h1>
{elem}
);
return (
<h1>Welcome</h1>
{(() => {
if (nameHidden) {
return <p>Hello</p>;
}
else {
return <p>Hello, {name}</p>;
}
})()}
);
return (
<h1>Welcome</h1>
<p>Hello {nameHidden ? null : (', ' + name)}</p>
);
return (
<h1>Welcome</h1>
<p>Hello {nameHidden || (', ' + name)}</p>
);// divで囲って1つの要素としている
return (
<div>
<h1>Hello</h1>
<p>JSX</p>
</div>
);App.js
export default function App() {
return (
<Label name="John" />
);
}
Label.js
export default function Label(props) {
return (
<>
<h1>Hello</h1>
<p>{props.name}</p>
</>
);
}
Label.js
export default function Label({ name = 'React' }) {
...
}
const [stateを格納する変数, stateの値を更新する関数] = useState(初期値)
Counter.js
import { useState } from 'react';
export default function Counter({ init }) {
const [count, setCount] = useState(init);
return (
<>
<p>{ count }</p>
<button onClick={ () => setCount( c => c + 1 ) }>++</button>
</>
);
}
export default function UserForm() {
const [form, setForm] = useState({
name: '',
email: ''
});
const formHandler = e => {
setForm({
...form,
[e.target.name]: e.target.value
})
};
return (
<form>
<p>User: {form.name}</p>
<p>Email: {form.email}</p>
<div>
<label htmlFor="name">Name</label>
<input id="name" name="name" type="text"
onChange={formHandler} value={form.name} />
</div>
<div>
<label htmlFor='email'>E-mail</label>
<input id="email" name="email" type="email"
onChange={formHandler} value={form.email} />
</div>
<div>
<button type="button" onClick={ () => alert(`Hello ${form.name}`)}>
送信
</button>
</div>
</form>
);
}export default function Counter() {
// countRefの値が変更されても再描画はされない
const countRef = useRef(0);
const handleClick = () => {
// Ref変数.currentで値にアクセスできる
countRef.current = countRef.current + 1;
};
return (
<>
<button onClick={handleClick}>Count++</button>
<button onClick={() => alert(countRef.current)}>Show</button>
</>
);
}useReducer( reducer, initialArg, init? )
export default function Counter({init = 0}) {
const [count, dispatch] = useReducer(
(count, action) => {
switch (action.type) {
case 'increment':
return count + 1;
case 'reset':
return init;
default:
throw Error('Unknown action: ' + action.type);
}
},
init
);
return (
<>
<p>{count}</p>
<button onClick={() => dispatch({type: 'increment'})}>++</button>
<button onClick={() => dispatch({type: 'reset'})}>reset</button>
</>
);
}
App.js
import {useReducer} from "react";
import AddNote from "./AddNote";
import NoteList from "./NoteList";
let initialNotes = [];
function notesReducer(notes, action) {
switch (action.type) {
case 'added': {
return [...notes, {
id: crypto.randomUUID(),
text: action.text,
}];
}
case 'edited': {
return notes.map( e => {
return e.id === action.note.id ? action.note : e;
});
}
case 'deleted': {
return notes.filter( e => e.id !== action.id);
}
default: {
throw Error('Unknown action: ' + action.type);
}
}
}
export default function App() {
const [notes, dispatch] = useReducer(
notesReducer,
initialNotes
);
// ノートを追加
function handleAddNote(text) {
dispatch({
type: 'added',
text: text,
});
}
// ノートを編集
function handleEditNote(note) {
dispatch({
type: 'edited',
note: note,
});
}
// ノートを削除
function handleDeleteNote(id) {
dispatch({
type: "deleted",
id: id,
});
}
return (
<>
<h1>Notes</h1>
<AddNote onAddNote={handleAddNote}/>
<NoteList
notes={notes}
onEditNote={handleEditNote}
onDeleteNote={handleDeleteNote}
/>
</>
);
}
AddNote.js
import {useState} from "react";
export default function AddNote({onAddNote}) {
const [text, setText] = useState('');
return (
<>
<input
placeholder="ノートを追加"
value={text}
onChange={e => setText(e.target.value)}
/>
<button onClick={() => {
onAddNote(text);
setText('');
}}>追加</button>
</>
);
}
NoteList.js
import {useState} from "react";
export default function NoteList({
notes,
onEditNote,
onDeleteNote,
}) {
return (
<>
{notes.map(e => (
<div key={e.id}>
<NoteRow
note={e}
onEdit={onEditNote}
onDelete={onDeleteNote}
/>
</div>
))}
</>
);
}
function NoteRow({
note,
onEdit,
onDelete
}) {
const [isEditing, setIsEditing] = useState(false);
if (isEditing) {
return (
<>
<input
value={note.text}
onChange={e => {
onEdit({
...note,
text: e.target.value
});
}} />
<button onClick={() => setIsEditing(false)}>
保存
</button>
</>
);
}
else {
return (
<>
{note.text}
<button onClick={() => setIsEditing(true)}>
編集
</button>
<button onClick={() => onDelete(note.id)}>
削除
</button>
</>
);
}
}
const Contextオブジェクト = createContext(defaultValue);
const 値 = useContext(Contextオブジェクト);
import {createContext, useContext} from "react";
export const MessageContext = createContext('hello');
export default function Context() {
return (
<>
{/* Context.Provider以下のコンポーネントではvalueの値になる */}
<MessageContext.Provider value='hello world'>
<Label /> {/* 'hello world'が描画される */}
</MessageContext.Provider>
{/* Context.Provider以下のコンポーネントでない場合はdefaultValueが使用される */}
<Label /> {/* defaultValueの'hello'が描画される */}
</>
);
}
function Label() {
return <Message />
}
function Message() {
const message = useContext(MessageContext);
return <p>{message}</p>
}