LoginSignup
1
0

More than 1 year has passed since last update.

VanillaなJavaScriptからReactを使い出した時の前後のコードを見つめてみる

Last updated at Posted at 2022-09-03

初めに

ただの記録です。
Reactに移る前のコードと移った後のコードを貼っているだけ。

VanilaなJavaScriptでの記載

移行前の前(createElementを多用)

document.createElementをひたすら使ってるパターンです
bodyの中身が全部tdでいいならさらにmapでいいんですが、
各カラムで別々の何かを適用させたい場合はひたすら変数が増えていくパターン...(嫌すぎる)

See the Pen Untitled by sinsky (@sky-sora) on CodePen.

コード(codepenの内容と一緒です)
<div id="root"></div>
window.addEventListener("DOMContentLoaded", () => {
  // 使用するデータ
  // https://www.tiobe.com/tiobe-index/
  const tableData = {
    head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
    body: [
      [1, 2, "up", "Python", 15.42, "+3.56"],
      [2, 1, "down", "C", 14.59, "+2.03"],
      [3, 3, "", "Java", 12.40, "+1.96"],
      [4, 4, "", "C++", 10.17, "+2.81"],
      [5, 5, "", "C#", 5.59, "+0.45"],
      [6, 6, "", "Visual Basic", 4.99, "0.33"],
      [7, 7, "", "JavaSCript", 2.33, "-0.61"],
      [8, 9, "up", "Assembly language", 2.17, "+0.14"],
      [9, 10, "up", "SQL", 1.70, "+0.23"],
      [10, 8, "down", "PHP", 1.39, "-0.80"]
    ],
  };
  const root = document.querySelector("#root");
  const table = document.createElement("table");

  const thead = document.createElement("thead");
  const thead_tr = document.createElement("tr");
  tableData.head.map(title => {
    const th = document.createElement("th");
    th.innerHTML = title;
    thead_tr.append(th);
  });
  thead.append(thead_tr);
  table.append(thead);

  const tbody = document.createElement("tbody");
  tableData.body.map(row => {
    const tr = document.createElement("tr");

    const [year, lastYear, change, lang, rate, diff] = row;
    const year_td = document.createElement("td");
    year_td.innerHTML = year;
    tr.append(year_td);
    const lastYear_td = document.createElement("td");
    lastYear_td.innerHTML = lastYear;
    tr.append(lastYear_td);
    const change_td = document.createElement("td");
    change_td.innerHTML = change;
    tr.append(change_td);
    const lang_td = document.createElement("td");
    lang_td.innerHTML = lang;
    tr.append(lang_td);
    const rate_td = document.createElement("td");
    rate_td.innerHTML = rate;
    tr.append(rate_td);
    const diff_td = document.createElement("td");
    diff_td.innerHTML = diff;
    tr.append(diff_td);
    tbody.append(tr);
  });
  table.append(tbody);
  root.append(table);
})

移行前(templateを利用する)

document.importNodeを利用して、HTMLに先に記載しているTemplateを使うやり方です
一つ前のやり方よりも、こっちの方がclassの定義とかを前もってできるので、
わざわざJavaScriptで書き換える必要がないというメリットがあります。
これを知ってからはcreateElementを使うことは無くなりました(HTMLでclassとかdata属性を管理したかったので)

See the Pen use template by sinsky (@sky-sora) on CodePen.

コード(codepenの内容と一緒です)
<div id="root">
  <table id="table">
    <thead></thear>
    <tbody></tbody>
  </table>
</div>
<template id="table-head">
  <tr>
    <th data-id="year"></th>
    <th data-id="lastYear"></th>
    <th data-id="change"></th>
    <th data-id="lang"></th>
    <th data-id="rate"></th>
    <th data-id="diff"></th>
  </tr>
</template>
<template id="table-body">
  <tr>
    <td data-id="year"></td>
    <td data-id="lastYear"></td>
    <td data-id="change"></td>
    <td data-id="lang"></td>
    <td data-id="rate"></td>
    <td data-id="diff"></td>
  </tr>
</template>
window.addEventListener("DOMContentLoaded", () => {
  // 使用するデータ
  // https://www.tiobe.com/tiobe-index/
  const tableData = {
    head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
    body: [
      [1, 2, "up", "Python", 15.42, "+3.56"],
      [2, 1, "down", "C", 14.59, "+2.03"],
      [3, 3, "", "Java", 12.40, "+1.96"],
      [4, 4, "", "C++", 10.17, "+2.81"],
      [5, 5, "", "C#", 5.59, "+0.45"],
      [6, 6, "", "Visual Basic", 4.99, "0.33"],
      [7, 7, "", "JavaSCript", 2.33, "-0.61"],
      [8, 9, "up", "Assembly language", 2.17, "+0.14"],
      [9, 10, "up", "SQL", 1.70, "+0.23"],
      [10, 8, "down", "PHP", 1.39, "-0.80"]
    ],
  };

  const table_head_content = document.querySelector("#table-head").content;
  const head_fragment = document.createDocumentFragment();

  const head_clone = document.importNode(table_head_content, true);
  const [year, lastYear, change, lang, rate, diff] = tableData.head;
  head_clone.querySelector("[data-id='year']").innerHTML = year;
  head_clone.querySelector("[data-id='lastYear']").innerHTML = lastYear;
  head_clone.querySelector("[data-id='change']").innerHTML = change;
  head_clone.querySelector("[data-id='lang']").innerHTML = lang;
  head_clone.querySelector("[data-id='rate']").innerHTML = rate;
  head_clone.querySelector("[data-id='diff']").innerHTML = diff;
  head_fragment.append(head_clone);
  document.querySelector('#table > thead').appendChild(head_fragment);

  // 長いから関数作ってみる
  const getId = (clone, id) => clone.querySelector(`[data-id='${id}']`);

  const table_body_content = document.querySelector("#table-body").content;
  const body_fragment = document.createDocumentFragment();
  tableData.body.map(row => {
    const body_clone = document.importNode(table_body_content, true);
    const [year, lastYear, change, lang, rate, diff] = row;
    getId(body_clone, "year").innerHTML = year;
    getId(body_clone, "lastYear").innerHTML = lastYear;
    getId(body_clone, "change").innerHTML = change;
    getId(body_clone, "lang").innerHTML = lang;
    getId(body_clone, "rate").innerHTML = rate;
    getId(body_clone, "diff").innerHTML = diff;
    body_fragment.append(body_clone);
  });
  document.querySelector('#table > tbody').appendChild(body_fragment);
});

Reactで書く

面倒になったのでコードだけな上に一つのコードにまとめています(しかもexportして終わり)

const Thead = ({ data }) => {
  const [year, lastYear, change, lang, rate, diff] = data;
  return (
    <thead>
      <tr>
        <th>{year}</th>
        <th>{lastYear}</th>
        <th>{change}</th>
        <th>{lang}</th>
        <th>{rate}</th>
        <th>{diff}</th>
      </tr>
    </thead>
  );
};
const Tbody = ({ data }) => {
  return (
    <tbody>
      {data.map((row) => {
        const [year, lastYear, change, lang, rate, diff] = row;
        return (
          <tr>
            <td>{year}</td>
            <td>{lastYear}</td>
            <td>{change}</td>
            <td>{lang}</td>
            <td>{rate}</td>
            <td>{diff}</td>
          </tr>
        );
      })}
    </tbody>
  );
};
export const App = () => {
  const tableData = {
    head: ["Aug 2022", "Aug 2021", "Change", "Programming Language", "Ratings", "Change"],
    body: [
      [1, 2, "up", "Python", 15.42, "+3.56"],
      [2, 1, "down", "C", 14.59, "+2.03"],
      [3, 3, "", "Java", 12.4, "+1.96"],
      [4, 4, "", "C++", 10.17, "+2.81"],
      [5, 5, "", "C#", 5.59, "+0.45"],
      [6, 6, "", "Visual Basic", 4.99, "0.33"],
      [7, 7, "", "JavaSCript", 2.33, "-0.61"],
      [8, 9, "up", "Assembly language", 2.17, "+0.14"],
      [9, 10, "up", "SQL", 1.7, "+0.23"],
      [10, 8, "down", "PHP", 1.39, "-0.80"],
    ],
  };
  return (
    <table>
      <Thead data={tableData.head} />
      <Tbody data={tableData.body} />
    </table>
  );
};

終わりに

こんな感じで移行したんだよってお話でした。
document.importNodeに慣れていたからか、
React(JSX)の方にも違和感なく書き換えることができました。
document.createElementの多用は何も考えずにJavaScriptだけ弄っていればいいので楽なんですが、
最終的なHTMLが想像しづらい上に、classなどの管理も非常に面倒だったなぁと書きながら思い出していました。

React言わずもがなですね。。。

Vanillaは気軽なモックを作るときにとてもお手軽なので、
Node.jsが使えない環境の時はとてもありがたいんですよね。
(CDNはBabelも導入しないとJSXが書けなかったり、CDNが業務上ネットワークでブロックされていたり(思い出したくない記憶))...
忘れないための備忘録的な意味も含めての投稿でした。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0