前置き
MDNのReactチュートリアルをやって学んだことの復習をしています。
この記事の#2です
本記事では「コンポーネント化」について復習しています。
何か間違いがあれば指摘していただけると大変励みになります。
Reactアプリのコンポーネント化
コンポーネント化
…アプリ内の要素を分割していき管理、記述しやすくしていくこと。
チュートリアルでは下記のような長ったらしいJSXを徐々にコンポーネント化していく
function App(props) {
return (
<div className="todoapp stack-large">
<h1>TodoMatic</h1>
<form>
<h2 className="label-wrapper">
<label htmlFor="new-todo-input" className="label__lg">
What needs to be done?
</label>
</h2>
<input
type="text"
id="new-todo-input"
className="input input__lg"
name="text"
autoComplete="off"
/>
<button type="submit" className="btn btn__primary btn__lg">
Add
</button>
</form>
<div className="filters btn-group stack-exception">
<button type="button" className="btn toggle-btn" aria-pressed="true">
<span className="visually-hidden">Show </span>
<span>all</span>
<span className="visually-hidden"> tasks</span>
{// ...略}
コンポーネント化
まずは各todoをliタグを使って記述している下記の部分
{// ...略}
<li className="todo stack-small">
<div className="c-cb">
<input id="todo-0" type="checkbox" defaultChecked={true} />
<label className="todo-label" htmlFor="todo-0">
Eat
</label>
</div>
<div className="btn-group">
<button type="button" className="btn">
Edit <span className="visually-hidden">Eat</span>
</button>
<button type="button" className="btn btn__danger">
Delete <span className="visually-hidden">Eat</span>
</button>
</div>
</li>
<li className="todo stack-small">
<div className="c-cb">
<input id="todo-1" type="checkbox" />
<label className="todo-label" htmlFor="todo-1">
Sleep
</label>
{// ...略}
まずは適切なコンポーネント名でファイルを作成する。
mkdir src/component
touch src/component/Todo.js
Todo.js
内でfunctionを定義しreturn()で、対象のtodoリストの一番最初の要素だけを返すようにします。
{// 定義と同時にエクスポートもしている}
export default function Todo() {
return (
<li className="todo stack-small">
<div className="c-cb">
<input id="todo-0" type="checkbox" defaultChecked={true} />
<label className="todo-label" htmlFor="todo-0">
Eat
</label>
</div>
<div className="btn-group">
<button type="button" className="btn">
Edit <span className="visually-hidden">Eat</span>
</button>
<button type="button" className="btn btn__danger">
Delete <span className="visually-hidden">Eat</span>
</button>
</div>
</li>
);
}
なぜ最初の要素だけなのかというと、id,defaultChecked,valueの値を除いて構成が同じだからです。
完成したコンポーネントをApp.jsで読み込んでみます。
{// todoコンポーネントをインポート}
import Todo from "./components/Todo";
{// ...略}
<ul
role="list"
className="todo-list stack-large stack-exception"
aria-labelledby="list-heading"
>
<Todo />
<Todo />
<Todo />
</ul>
{// ...略}
しかしこのままでは同じタスクを3回表示してしまうだけです。それぞれのid.defaultChecked,valueの値をユニークなものにしなければなりません。そこでApp.jsの親コンポーネントであるindex.jsにそれぞれのtodoを定義してしまいます。
{// ...略}
const DATA = [
{ id: "todo-0", name: "Eat", completed: true },
{ id: "todo-1", name: "Sleep", completed: false },
{ id: "todo-2", name: "Repeat", completed: false }
];
ReactDOM.render(<App tasks={DATA} />, document.getElementById('root'));
{// ...略}
こうすることでApp.jsでprops.tasksを使って値を受け取ることができます。
が、これをそのまま表示してしまうと下記のように代入した値がそのまま表示されていしまいます。(nameだけを表示)
なので上記のmap()関数からtodoコンポーネントを返す必要も出てきます。
{// ...略}
const taskList = tasks.map(task => (
<Todo
id={task.id}
name={task.name}
completed={task.completed}
key={task.id}
toggleTaskCompleted={toggleTaskCompleted}
/>
)
);
{// ...略}
他の部分も同じ要領でコンポーネント化していきます。
終わりに
次の記事では「イベント」について復習していきたいと思います。