FrontPage

目次

JavaScriptモジュールバンドラ

Vite

Node.js

npm

React

その他のフレームワークと特徴

フレームワーク特徴
AngularJSMVCに対応したフルスタックフレームワーク.パフォーマンス面でReactとVue.jsに負けている
Vue.jsUIに特化したフレームワーク.Reactと比較すると少しパフォーマンス面で劣っている
試してはいないググった情報

プロジェクトの作成と実行

# プロジェクトの作成
% npx create-react-app プロジェクト名

# (対象ディレクトリに移動して)Reactプロジェクトの実行
% npm start

初期状態

コンポーネント

関数コンポーネント
関数として定義
クラスコンポーネント
class構文で定義

JSX

式を埋め込む

const name = "John";
const element = <h1>Hello, {name}</h1>;

// 変数と文字列を結合した場合は`{...}`内で行う
// 属性値を指定する場合は`"{...}"`のように囲わない
const profile = <img src={'https://profile/' + name + '.jpg' />;

無視される値

条件分岐

if文

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>;
      }
   })()}
);

3項演算子

return (
   <h1>Welcome</h1>
   <p>Hello {nameHidden ? null : (', ' + name)}</p>
);

短絡評価

ルート要素

Props

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' }) {
   ...
}

State

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>
      </>
   );
}

Form

Ref

Reducer

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>
           </>
       );
   }
}

Context

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>
}

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS