JavaScript の基礎

React のコードでよく出てくる JavaScript だけ

ポイント

  • React で迷うのは、たいてい React ではなく JavaScript。一覧の関数・比べる記号・書き方の3つに分けて並べた
  • map・filter・...(スプレッド)は、元の一覧を変えずに「新しい一覧」を作る。だから React の state と相性がいい
  • 知らない書き方は、下の表で「決まり」を1文読んでから、デモで試す

早見表

一覧(配列)の関数

書き方決まり(1文)例
.map((x) => …)1つずつ取り出して、形を変えた新しい一覧を作るmembers.map((m) => <li>{m.name}</li>)
.filter((x) => 条件)条件に合うものだけを残した新しい一覧を作るmembers.filter((m) => m.plan === "有料")
.find((x) => 条件)条件に合う最初の1つを返すmembers.find((m) => m.id === 2)
.sort((a, b) => 数)2つずつ比べて並び替える。答えがマイナスなら a が前[...items].sort((a, b) => a.price - b.price)
.slice(始まり, 終わり)始まりから、終わりの手前までを切り出す(0 から数える)items.slice(0, 6)
.reduce((合計, x) => …, 0)1つずつ見て、1つの値(合計など)にまとめるitems.reduce((sum, i) => sum + i.price, 0)
.includes(x)x が入っているか(true/false)name.includes(query)
.length一覧なら個数、文字なら文字数{members.length}人
.some((x) => 条件)1つでも条件に合うものがあるか(true/false)items.some((i) => i.stock === 0)
.join(区切り)一覧を、区切りでつないだ1つの文字にするtags.join("・")

比べる・つなぐ

書き方決まり(1文)例
===左と右が同じかplan === "有料"
!==左と右が同じではないかm.id !== id
> >= < <=より大きい・以上・より小さい・以下quantity >= stock
!反対にする(true ↔ false)!isOpen
&&かつ。JSX では「合っていれば出す」{error && <p>{error}</p>}
||または!isDirty || isSubmitting
条件 ? A : B合っていれば A、違えば B{open ? "閉じる" : "開く"}
a ?? ba が空っぽ(null・undefined)なら b を使うuser.name ?? "ゲスト"
a?.ba が空っぽでもエラーにせず、undefined にするuser?.name

書き方

書き方決まり(1文)例
(x) => …関数を作る(x を受け取って、…する)() => setCount(count + 1)
(x) => { … }中に何行も書ける関数onClick={() => { reset(); setSent(false) }}
const と letconst は入れかえない、let はあとで入れかえるlet sorted = filtered
const [a, setA] = …返ってきた2つに名前を付けて取り出すconst [count, setCount] = useState(0)
const { a, b } = …箱({ })の中から、使うものだけ名前で取り出すconst { user } = useAuth()
function X({ a })部品に渡されたもの(props)を、名前で受け取るfunction Card({ title }) { … }
`…${x}…`文字の中に、値を入れる(テンプレート文字列)`${count}件`
[...x, 足す]一覧をコピーして、最後に足した新しい一覧setMembers([...members, newMember])
{ ...x, 名札: 値 }1つ分をコピーして、1か所だけ変えた新しい1つ分{ ...member, id: 7 }
import/exportほかのファイルの部品を使う/ほかのファイルに出すimport { Button } from "./button"
async/await時間のかかること(データの取得など)が終わるのを待つconst res = await fetch(url)

試してみよう

import { useState } from "react"

// 会員の一覧(最初の3人)
const initialMembers = [
  { id: 1, name: "花子", plan: "有料" },
  { id: 2, name: "一郎", plan: "無料" },
  { id: 3, name: "美咲", plan: "有料" },
]

export default function App() {
  // 会員の一覧(「1人足す」で増える)
  const [members, setMembers] = useState(initialMembers)
  // 「有料だけ見る」が押されているか(true = 押されている)
  const [paidOnly, setPaidOnly] = useState(false)

  // 画面に出す一覧:押されていたら有料の人だけ、押されていなかったら全員
  const shown = paidOnly ? members.filter((member) => member.plan === "有料") : members

  // 1人足す:今の会員を全員並べて、その最後に新しい1人を足した一覧にする
  function addMember() {
    const newId = members.length + 1
    setMembers([...members, { id: newId, name: "会員" + newId, plan: "無料" }])
  }

  return (
    <div style={{ padding: 16, fontFamily: "sans-serif" }}>
      <div style={{ display: "flex", gap: 8 }}>
        {/* 押すたびに、有料だけ ↔ 全員 を切り替える(! = 反対にする) */}
        <button onClick={() => setPaidOnly(!paidOnly)}>{paidOnly ? "全員を見る" : "有料だけ見る"}</button>
        <button onClick={() => addMember()}>1人足す</button>
      </div>
      <p>{shown.length}人</p>
      {/* 画面に出す一覧を、1人ずつ「名前(プラン)」の行にする */}
      <ul>
        {shown.map((member) => (
          <li key={member.id}>
            {member.name}({member.plan})
          </li>
        ))}
      </ul>
    </div>
  )
}
  1. 「有料だけ見る」を押してみよう(filter で、有料の人だけの新しい一覧ができる)
  2. "有料" を "無料" に変えてみよう
  3. 「1人足す」を何回か押してみよう([...members, 新しい人] で、最後に1人ずつ増える)

つまずきポイント

members.push(人) では画面が変わらない
push は元の一覧を書きかえるだけで、React は変わったことに気づかない。[...members, 人] で新しい一覧を作って、setMembers に渡す。
.sort は元の一覧を書きかえる
map や filter とちがって、sort は元の一覧そのものを並べ替える。[...items].sort(…) と、コピーしてから並べる。
= は「入れる」、=== は「同じか」
条件の中で = と書くと、比べずに値を入れてしまう。比べるときは ===。