JavaScript ใฎ้…ๅˆ—ใฏใƒŸใƒฅใƒผใ‚ฟใƒ–ใƒซ๏ผˆmutable, ๆ›ธใๆ›ใˆๅฏ่ƒฝ๏ผ‰ใชใ‚‚ใฎใงใ™ใŒใ€state ใซๆ ผ็ดใ™ใ‚‹ๅ ดๅˆใฏใ‚คใƒŸใƒฅใƒผใ‚ฟใƒ–ใƒซ๏ผˆimmutable, ๆ›ธใๆ›ใˆไธ่ƒฝ๏ผ‰ใจใ—ใฆๆ‰ฑใ†ในใใงใ™ใ€‚ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๆ™‚ใจๅŒๆง˜ใซใ€state ใซไฟๅญ˜ใ•ใ‚ŒใŸ้…ๅˆ—ใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ๅ ดๅˆใฏใ€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใ—ใฆ๏ผˆใพใŸใฏๆ—ขๅญ˜ใฎ้…ๅˆ—ใ‚’ใ‚ณใƒ”ใƒผใ—ใฆ๏ผ‰ใ€ใใฎๆ–ฐใ—ใ„้…ๅˆ—ใง state ใ‚’ใ‚ปใƒƒใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

ใ“ใฎใƒšใƒผใ‚ธใงๅญฆใถใ“ใจ

  • React ใฎ state ๅ†…ใซใ‚ใ‚‹้…ๅˆ—ใซๅฏพใ—่ฆ็ด ใฎ่ฟฝๅŠ ใ€ๅ‰Š้™คใ€ๅค‰ๆ›ดใ‚’่กŒใ†ๆ–นๆณ•
  • ้…ๅˆ—ๅ†…ใซใ‚ใ‚‹ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ๆ–นๆณ•
  • Immer ใ‚’ไฝฟใฃใฆ้…ๅˆ—ใ‚ณใƒ”ใƒผใฎใŸใ‚ใฎใ‚ณใƒผใƒ‰ใฎๅ†—้•ทใ•ใ‚’็ทฉๅ’Œใ™ใ‚‹ๆ–นๆณ•

้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใšใซๆ›ดๆ–ฐใ™ใ‚‹

JavaScript ใซใŠใ„ใฆใ€้…ๅˆ—ใจใฏๅ˜ใชใ‚‹ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎไธ€็จฎใงใ™ใ€‚ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใจใใจๅŒๆง˜ใซใ€React ใฎ state ๅ†…ใซใ‚ใ‚‹้…ๅˆ—ใฏใ€่ชญใฟๅ–ใ‚Šๅฐ‚็”จใจใ—ใฆๆ‰ฑใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€arr[0] = 'bird' ใฎใ‚ˆใ†ใชๅฝขใง้…ๅˆ—ๅ†…ใฎ่ฆ็ด ใซๅ†ไปฃๅ…ฅใ‚’่กŒใฃใฆใฏใชใ‚‰ใšใ€push() ใ‚„ pop() ใฎใ‚ˆใ†ใช้…ๅˆ—ใ‚’ใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณ๏ผˆmutation, ๆ›ธใๆ›ใˆ๏ผ‰ใ™ใ‚‹ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟใฃใฆใ‚‚ใ„ใ‘ใชใ„ใจใ„ใ†ใ“ใจใงใ™ใ€‚

ไปฃใ‚ใ‚Šใซใ€ใ„ใคใงใ‚‚้…ๅˆ—ใ‚’ๆ›ดๆ–ฐใ—ใŸใ„ใจใใซใฏใ€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ state ใ‚ปใƒƒใ‚ฟ้–ขๆ•ฐใซๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใŸใ‚ใซใ€state ใ‹ใ‚‰ๅ–ใ‚Šๅ‡บใ—ใŸๅ…ƒใฎ้…ๅˆ—ใ‹ใ‚‰ใ€filter() ใ‚„ map() ใจใ„ใฃใŸๆ›ธใๆ›ใˆใ‚’่กŒใ‚ใชใ„ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅ‘ผใณๅ‡บใ™ใ“ใจใงใ€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ใใ—ใฆใ€็ตๆžœใจใ—ใฆๅพ—ใ‚‰ใ‚ŒใŸๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ state ใซใ‚ปใƒƒใƒˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚

ไปฅไธ‹ใฏใ€ไธ€่ˆฌ็š„ใช้…ๅˆ—ๆ“ไฝœใฎๅ‚็…ง่กจใงใ™ใ€‚React ใฎ state ๅ†…ใฎ้…ๅˆ—ใ‚’ๆ‰ฑใ†้š›ใซใฏใ€ๅทฆใฎๅˆ—ใซใ‚ใ‚‹ใƒกใ‚ฝใƒƒใƒ‰ใ‚’้ฟใ‘ใฆใ€ๅณใฎๅˆ—ใซใ‚ใ‚‹ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ :

ไฝฟใ‚ใชใ„๏ผˆ้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใ‚‹๏ผ‰ไฝฟใ†๏ผˆๆ–ฐใ—ใ„้…ๅˆ—ใ‚’่ฟ”ใ™๏ผ‰
่ฟฝๅŠ push, unshiftconcat, [...arr] spread syntax (ไพ‹)
ๅ‰Š้™คpop, shift, splicefilter, slice (ไพ‹)
่ฆ็ด ็ฝฎๆ›splice, arr[i] = ... ไปฃๅ…ฅๆ–‡map (ไพ‹)
ใ‚ฝใƒผใƒˆreverse, sortๅ…ˆใซ้…ๅˆ—ใ‚’ใ‚ณใƒ”ใƒผ (ไพ‹)

ใพใŸใ€ใฉใกใ‚‰ใฎๅˆ—ใฎใƒกใ‚ฝใƒƒใƒ‰ใ‚‚ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ‚Œใ‚‹ Immer ใ‚’ไฝฟใ†ๆ–นๆณ•ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚

่ฝใจใ—็ฉด

ๆฎ‹ๅฟตใชใŒใ‚‰ใ€slice ใจ splice ใฏๅๅ‰ใŒไผผใฆใ„ใ‚‹ใ‚‚ใฎใฎใ€้žๅธธใซ็•ฐใชใ‚‹ใ‚‚ใฎใงใ™ใ€‚

  • slice ใฏ้…ๅˆ—ใ‚„้…ๅˆ—ใฎไธ€้ƒจใ‚’ใ‚ณใƒ”ใƒผใ—ใพใ™ใ€‚
  • splice ใฏ๏ผˆ่ฆ็ด ใฎๆŒฟๅ…ฅใ‚„ๅ‰Š้™คใจใ„ใ†๏ผ‰้…ๅˆ—ใฎใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่กŒใ„ใพใ™ใ€‚

React ใงใฏใ€state ๅ†…ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚„้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใŸใใชใ„ใŸใ‚ใ€slice๏ผˆp ใชใ—๏ผ๏ผ‰ใฎๆ–นใ‚’ใ‚ˆใ‚Š้ ป็นใซไฝฟ็”จใ—ใพใ™ใ€‚ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๆ›ดๆ–ฐใงใ€ใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใจใฏไฝ•ใ‹ใ€ใใ‚ŒใŒใชใœ state ใซใŠใ„ใฆๆŽจๅฅจใ•ใ‚Œใชใ„ใ‹ใซใคใ„ใฆ่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใพใ™ใ€‚

้…ๅˆ—ใซ่ฆ็ด ใ‚’่ฟฝๅŠ 

push() ใฏ้…ๅˆ—ใฎๆ›ธใๆ›ใˆใ‚’่กŒใ„ใพใ™ใ€‚ใ“ใ‚Œใฏ้ฟใ‘ใ‚‹ในใใงใ™ใ€‚

import { useState } from 'react';

let nextId = 0;

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState([]);

  return (
    <>
      <h1>Inspiring sculptors:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={() => {
        artists.push({
          id: nextId++,
          name: name,
        });
      }}>Add</button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

ไปฃใ‚ใ‚Šใซใ€ๆ—ขๅญ˜ใฎ่ฆ็ด ใฎๆœซๅฐพใซๆ–ฐใ—ใ„่ฆ็ด ใŒๅŠ ใ‚ใฃใŸใ€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏ่ค‡ๆ•ฐใฎๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใŒใ€ใ‚‚ใฃใจใ‚‚็ฐกๅ˜ใชใฎใฏ ... ใจใ„ใ†้…ๅˆ—ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ™ใ€‚

setArtists( // Replace the state
[ // with a new array
...artists, // that contains all the old items
{ id: nextId++, name: name } // and one new item at the end
]
);

ใ“ใ‚Œใงๆญฃใ—ใๅ‹•ไฝœใ—ใพใ™ใ€‚

import { useState } from 'react';

let nextId = 0;

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState([]);

  return (
    <>
      <h1>Inspiring sculptors:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={() => {
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Add</button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

้…ๅˆ—ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใ‚’ไฝฟ็”จใ™ใ‚Œใฐใ€ๅ…ƒใฎ ...artists ใฎๅ…ˆ้ ญใซ่ฆ็ด ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™๏ผš

setArtists([
{ id: nextId++, name: name },
...artists // Put old items at the end
]);

ใ“ใฎใ‚ˆใ†ใซใ€ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใฏใ€push() ใง้…ๅˆ—ใฎๆœซๅฐพใซ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใจ unshift() ใง้…ๅˆ—ใฎๅ…ˆ้ ญใซ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใฎไธกๆ–นใฎๅฝนๅ‰ฒใ‚’ๆžœใŸใ›ใพใ™ใ€‚ไธŠ่จ˜ใฎใ‚ตใƒณใƒ‰ใƒœใƒƒใ‚ฏใ‚นใง่ฉฆใ—ใฆใฟใฆใใ ใ•ใ„๏ผ

้…ๅˆ—ใ‹ใ‚‰่ฆ็ด ใ‚’ๅ‰Š้™ค

้…ๅˆ—ใ‹ใ‚‰่ฆ็ด ใ‚’ๅ‰Š้™คใ™ใ‚‹ๆœ€ใ‚‚็ฐกๅ˜ใชๆ–นๆณ•ใฏใ€ใใ‚Œใ‚’ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ—ใฆๅ–ใ‚Š้™คใ„ใŸใ€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœใ‚‹ใ“ใจใงใ™ใ€‚ใคใพใ‚Šใ€ใใฎ่ฆ็ด ใ‚’ๅซใพใชใ„ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏ filter ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ไพ‹ใˆใฐ๏ผš

import { useState } from 'react';

let initialArtists = [
  { id: 0, name: 'Marta Colvin Andrade' },
  { id: 1, name: 'Lamidi Olonade Fakeye'},
  { id: 2, name: 'Louise Nevelson'},
];

export default function List() {
  const [artists, setArtists] = useState(
    initialArtists
  );

  return (
    <>
      <h1>Inspiring sculptors:</h1>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>
            {artist.name}{' '}
            <button onClick={() => {
              setArtists(
                artists.filter(a =>
                  a.id !== artist.id
                )
              );
            }}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </>
  );
}

ไฝ•ๅบฆใ‹ โ€œDeleteโ€ ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆๅ‹•ไฝœใ‚’็ขบ่ชใ—ใŸใ‚‰ใ€ใ‚ฏใƒชใƒƒใ‚ฏใƒใƒณใƒ‰ใƒฉใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚

setArtists(
artists.filter(a => a.id !== artist.id)
);

ใ“ใ“ใงใ€artists.filter(a => a.id !== artist.id) ใจใ„ใ†ใ‚ณใƒผใƒ‰ใฏใ€Œartist.id ใจ็•ฐใชใ‚‹ ID ใ‚’ๆŒใค artists ใฎใฟใฎ้…ๅˆ—ใ‚’ไฝœๆˆใ™ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใ™ใ€‚่จ€ใ„ๆ›ใˆใ‚‹ใจใ€ๅ„ใ‚ขใƒผใƒ†ใ‚ฃใ‚นใƒˆใฎ โ€œDeleteโ€ ใƒœใ‚ฟใƒณใฏใ€่ฉฒๅฝ“ใ‚ขใƒผใƒ†ใ‚ฃใ‚นใƒˆใ‚’้…ๅˆ—ใ‹ใ‚‰ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ—ใฆๅ–ใ‚Š้™คใใ€็ตๆžœใจใ—ใฆๅพ—ใ‚‰ใ‚Œใ‚‹้…ๅˆ—ใงๅ†ใƒฌใƒณใƒ€ใƒผใ‚’่ฆๆฑ‚ใ—ใพใ™ใ€‚filter ใฏๅ…ƒใฎ้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚

้…ๅˆ—ใฎๅค‰ๆ›

้…ๅˆ—ใฎไธ€้ƒจใพใŸใฏใ™ในใฆใฎ่ฆ็ด ใ‚’ๅค‰ๆ›ดใ—ใŸใ„ๅ ดๅˆใฏใ€map() ใ‚’ไฝฟ็”จใ—ใฆๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใงใใพใ™ใ€‚map ใซๆธกใ™้–ขๆ•ฐใฏใ€ใƒ‡ใƒผใ‚ฟใ‚„ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น๏ผˆใพใŸใฏใใฎไธกๆ–น๏ผ‰ใซๅŸบใฅใ„ใฆๅ„่ฆ็ด ใซไฝ•ใ‚’ใ™ใ‚‹ใ‹ใ‚’ๆฑบๅฎšใงใใพใ™ใ€‚

ใ“ใฎไพ‹ใงใฏใ€้…ๅˆ—ใซ 2 ใคใฎๅ††ใจ 1 ใคใฎๆญฃๆ–นๅฝขใฎๅบงๆจ™ใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ใƒœใ‚ฟใƒณใ‚’ๆŠผใ™ใจใ€ๅ††ใ ใ‘ใŒ 50 ใƒ”ใ‚ฏใ‚ปใƒซไธ‹ใซ็งปๅ‹•ใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€map() ใ‚’ไฝฟ็”จใ—ใฆๆ–ฐใ—ใ„ใƒ‡ใƒผใ‚ฟใฎ้…ๅˆ—ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใง่กŒใ‚ใ‚Œใพใ™ใ€‚

import { useState } from 'react';

let initialShapes = [
  { id: 0, type: 'circle', x: 50, y: 100 },
  { id: 1, type: 'square', x: 150, y: 100 },
  { id: 2, type: 'circle', x: 250, y: 100 },
];

export default function ShapeEditor() {
  const [shapes, setShapes] = useState(
    initialShapes
  );

  function handleClick() {
    const nextShapes = shapes.map(shape => {
      if (shape.type === 'square') {
        // No change
        return shape;
      } else {
        // Return a new circle 50px below
        return {
          ...shape,
          y: shape.y + 50,
        };
      }
    });
    // Re-render with the new array
    setShapes(nextShapes);
  }

  return (
    <>
      <button onClick={handleClick}>
        Move circles down!
      </button>
      {shapes.map(shape => (
        <div
          key={shape.id}
          style={{
          background: 'purple',
          position: 'absolute',
          left: shape.x,
          top: shape.y,
          borderRadius:
            shape.type === 'circle'
              ? '50%' : '',
          width: 20,
          height: 20,
        }} />
      ))}
    </>
  );
}

้…ๅˆ—ๅ†…ใฎ่ฆ็ด ใฎ็ฝฎๆ›

้…ๅˆ—ๅ†…ใฎไธ€้ƒจใฎ่ฆ็ด ใ ใ‘ใ‚’็ฝฎใๆ›ใˆใŸใ„ๅ ดๅˆใŒใ‚ˆใใ‚ใ‚Šใพใ™ใ€‚arr[0] = 'bird' ใฎใ‚ˆใ†ใชไปฃๅ…ฅใฏๅ…ƒใฎ้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใฆใ—ใพใ†ใฎใงใ€ไปฃใ‚ใ‚Šใซใ“ใ“ใงใ‚‚ map ใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

่ฆ็ด ใ‚’็ฝฎใๆ›ใˆใ‚‹ใซใฏใ€map ใ‚’ไฝฟใฃใฆๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚map ใฎๅ‘ผใณๅ‡บใ—ๅ†…ใงใฏใ€็ฌฌ 2 ๅผ•ๆ•ฐใจใ—ใฆ่ฆ็ด ใฎใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใ‚’ไฝฟ็”จใ—ใฆใ€ๅ…ƒใฎ่ฆ็ด ๏ผˆ็ฌฌ 1 ๅผ•ๆ•ฐ๏ผ‰ใ‚’่ฟ”ใ™ใ‹ใ€ไป–ใฎใ‚‚ใฎใ‚’่ฟ”ใ™ใ‹ใ‚’ๆฑบๅฎšใ—ใพใ™ใ€‚

import { useState } from 'react';

let initialCounters = [
  0, 0, 0
];

export default function CounterList() {
  const [counters, setCounters] = useState(
    initialCounters
  );

  function handleIncrementClick(index) {
    const nextCounters = counters.map((c, i) => {
      if (i === index) {
        // Increment the clicked counter
        return c + 1;
      } else {
        // The rest haven't changed
        return c;
      }
    });
    setCounters(nextCounters);
  }

  return (
    <ul>
      {counters.map((counter, i) => (
        <li key={i}>
          {counter}
          <button onClick={() => {
            handleIncrementClick(i);
          }}>+1</button>
        </li>
      ))}
    </ul>
  );
}

้…ๅˆ—ใธใฎๆŒฟๅ…ฅ

ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€ๅ…ˆ้ ญใงใ‚‚็ต‚็ซฏใงใ‚‚ใชใ„็‰นๅฎšใฎไฝ็ฝฎใซ่ฆ็ด ใ‚’ๆŒฟๅ…ฅใ—ใŸใ„ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใ‚’่กŒใ†ใซใฏใ€... ้…ๅˆ—ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใจ slice() ใƒกใ‚ฝใƒƒใƒ‰ใ‚’็ต„ใฟๅˆใ‚ใ›ใฆไฝฟ็”จใงใใพใ™ใ€‚slice() ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€้…ๅˆ—ใฎใ€Œใ‚นใƒฉใ‚คใ‚นใ€ใ‚’ๅˆ‡ใ‚Šๅ–ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚่ฆ็ด ใ‚’ๆŒฟๅ…ฅใ™ใ‚‹ใซใฏใ€ๆŒฟๅ…ฅใƒใ‚คใƒณใƒˆใฎๅ‰ใฎใ‚นใƒฉใ‚คใ‚นใ€ๆ–ฐใ—ใ„่ฆ็ด ใ€ๅ…ƒใฎ้…ๅˆ—ใฎๆฎ‹ใ‚Šใฎ้ƒจๅˆ†ใ‹ใ‚‰ใชใ‚‹้…ๅˆ—ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚

ใ“ใฎไพ‹ใงใฏใ€โ€œInsertโ€ ใƒœใ‚ฟใƒณใฏๅธธใซใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น 1 ใฎๅ ดๆ‰€ใซๆŒฟๅ…ฅใ‚’่กŒใ„ใพใ™ใ€‚

import { useState } from 'react';

let nextId = 3;
const initialArtists = [
  { id: 0, name: 'Marta Colvin Andrade' },
  { id: 1, name: 'Lamidi Olonade Fakeye'},
  { id: 2, name: 'Louise Nevelson'},
];

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState(
    initialArtists
  );

  function handleClick() {
    const insertAt = 1; // Could be any index
    const nextArtists = [
      // Items before the insertion point:
      ...artists.slice(0, insertAt),
      // New item:
      { id: nextId++, name: name },
      // Items after the insertion point:
      ...artists.slice(insertAt)
    ];
    setArtists(nextArtists);
    setName('');
  }

  return (
    <>
      <h1>Inspiring sculptors:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={handleClick}>
        Insert
      </button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

้…ๅˆ—ใธใฎใใฎไป–ใฎๅค‰ๆ›ด

ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใ‚„ใ€map()ใ€filter() ใชใฉใฎๆ›ธใๆ›ใˆใ‚’่กŒใ‚ใชใ„ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ ใ‘ใงใฏไธๅฏ่ƒฝใชใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐใ€้…ๅˆ—ใ‚’้€†้ †ใซใ—ใŸใ‚Šใ€ใ‚ฝใƒผใƒˆใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใพใ›ใ‚“ใ€‚JavaScript ใฎ reverse() ใ‚„ sort() ใƒกใ‚ฝใƒƒใƒ‰ใฏๅ…ƒใฎ้…ๅˆ—ใ‚’ๆ›ธใๆ›ใˆใ‚‹ใŸใ‚ใ€็›ดๆŽฅไฝฟใ†ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚

ใŸใ ใ—ใ€ๆœ€ๅˆใซ้…ๅˆ—ใ‚’ใ‚ณใƒ”ใƒผใ—ใฆใ‹ใ‚‰ใ€ใใฎใ‚ณใƒ”ใƒผใซๅค‰ๆ›ดใ‚’ๅŠ ใˆใ‚‹ใ“ใจใฏใงใใพใ™ใ€‚

ไพ‹ใˆใฐใ€ๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚

import { useState } from 'react';

const initialList = [
  { id: 0, title: 'Big Bellies' },
  { id: 1, title: 'Lunar Landscape' },
  { id: 2, title: 'Terracotta Army' },
];

export default function List() {
  const [list, setList] = useState(initialList);

  function handleClick() {
    const nextList = [...list];
    nextList.reverse();
    setList(nextList);
  }

  return (
    <>
      <button onClick={handleClick}>
        Reverse
      </button>
      <ul>
        {list.map(artwork => (
          <li key={artwork.id}>{artwork.title}</li>
        ))}
      </ul>
    </>
  );
}

ใ“ใ“ใงใฏใ€[...list] ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใ‚’ไฝฟใฃใฆใ€ๆœ€ๅˆใซๅ…ƒใฎ้…ๅˆ—ใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ‚ณใƒ”ใƒผใŒใงใใŸใ‚‰ใ€nextList.reverse() ใ‚„ nextList.sort() ใชใฉใฎใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณๅž‹ใฎใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟใฃใŸใ‚Šใ€nextList[0] = "something" ใงๅ€‹ใ€…ใฎ่ฆ็ด ใซไปฃๅ…ฅใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚

ใŸใ ใ—ใ€้…ๅˆ—ใ‚’ใ‚ณใƒ”ใƒผใ—ใฆใ‚‚ใ€ใใฎไธญใฎๆ—ขๅญ˜ใฎใ‚ขใ‚คใƒ†ใƒ ใ‚’็›ดๆŽฅๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ใ“ใ‚Œใฏใ€ใ‚ณใƒ”ใƒผใŒๆต…ใ (shallow) ่กŒใ‚ใ‚Œใ‚‹ใŸใ‚ใงใ™ใ€‚ๆ–ฐใ—ใ„้…ๅˆ—ใซใฏใ€ๅ…ƒใฎ้…ๅˆ—ใจๅŒใ˜่ฆ็ด ใŒๅซใพใ‚Œใพใ™ใ€‚ใใฎใŸใ‚ใ€ใ‚ณใƒ”ใƒผใ•ใ‚ŒใŸ้…ๅˆ—ๅ†…ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ›ธใๆ›ใˆใ‚‹ใจใ€ๆ—ขๅญ˜ใฎ state ใŒๆ›ธใๆ›ใˆใ‚‰ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐใ€ใ“ใฎใ‚ˆใ†ใชใ‚ณใƒผใƒ‰ใฏๅ•้กŒใŒใ‚ใ‚Šใพใ™ใ€‚

const nextList = [...list];
nextList[0].seen = true; // Problem: mutates list[0]
setList(nextList);

nextList ใจ list ใฏ็•ฐใชใ‚‹ 2 ใคใฎ้…ๅˆ—ใงใ™ใŒใ€nextList[0] ใจ list[0] ใฏๅŒใ˜ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆŒ‡ใ—ใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€nextList[0].seen ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใงใ€list[0].seen ใ‚‚ๅค‰ๆ›ดใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏ state ใฎใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใงใ‚ใ‚Šใ€้ฟใ‘ใ‚‹ในใใงใ™๏ผ ใ“ใฎๅ•้กŒใฏใ€ใƒใ‚นใƒˆใ•ใ‚ŒใŸ JavaScript ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๆ›ดๆ–ฐใจๅŒๆง˜ใฎๆ–นๆณ•ใง่งฃๆฑบใงใใพใ™ใ€‚ๅค‰ๆ›ดใ‚’ๅŠ ใˆใŸใ„ๅ€‹ใ€…ใฎ่ฆ็ด ใ‚’ใ€ๆ›ธใๆ›ใˆใ‚‹ไปฃใ‚ใ‚Šใซใ‚ณใƒ”ใƒผใ™ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ไปฅไธ‹ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚

้…ๅˆ—ๅ†…ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ›ดๆ–ฐใ™ใ‚‹

ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏใ€ๅฎŸ้š›ใซใฏ้…ๅˆ—ใฎใ€Œไธญใซใ€ใ‚ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ‚ณใƒผใƒ‰ไธญใงใฏใ€Œไธญใซใ€ใ‚ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใˆใพใ™ใŒใ€้…ๅˆ—ๅ†…ใฎๅ„ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏใใ‚Œใžใ‚Œ็‹ฌ็ซ‹ใ—ใŸๅ€คใงใ‚ใ‚Šใ€้…ๅˆ—ใฏใใ‚Œใ‚‰ใ‚’ใ€Œๅ‚็…งใ€ใ—ใฆใ„ใพใ™ใ€‚ใ“ใ‚ŒใŒใ€list[0] ใฎใ‚ˆใ†ใชใƒใ‚นใƒˆใ—ใŸใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅค‰ๆ›ดใ™ใ‚‹้š›ใซๆณจๆ„ใŒๅฟ…่ฆใช็†็”ฑใงใ™ใ€‚ไป–ใฎไบบใฎใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใƒชใ‚นใƒˆใŒใ€้…ๅˆ—ใฎๅŒใ˜่ฆ็ด ใ‚’ๆŒ‡ใ—ใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“๏ผ

ใƒใ‚นใƒˆใ•ใ‚ŒใŸ state ใ‚’ๆ›ดๆ–ฐใ™ใ‚‹้š›ใซใฏใ€ๆ›ดๆ–ฐใ—ใŸใ„็ฎ‡ๆ‰€ใ‹ใ‚‰ใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซใพใงใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใฉใฎใ‚ˆใ†ใซ่กŒใ†ใฎใ‹่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚

ใ“ใฎไพ‹ใงใฏใ€2 ใคใฎๅˆฅใ€…ใฎใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใƒชใ‚นใƒˆใŒๅŒใ˜ๅˆๆœŸ state ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฏ็‹ฌ็ซ‹ใ—ใฆใ„ใ‚‹ใ“ใจใซใชใฃใฆใ„ใ‚‹ใฎใงใ™ใŒใ€ใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใŒ่ตทใใฆใ„ใ‚‹ใŸใ‚ state ใŒ่ชคใฃใฆๅ…ฑๆœ‰ใ•ใ‚Œใ€ไธ€ๆ–นใฎใƒชใ‚นใƒˆใงใƒœใƒƒใ‚ฏใ‚นใ‚’ใƒใ‚งใƒƒใ‚ฏใ™ใ‚‹ใจใ‚‚ใ†ไธ€ๆ–นใฎใƒชใ‚นใƒˆใซๅฝฑ้Ÿฟใ—ใฆใ—ใพใฃใฆใ„ใพใ™ใ€‚

import { useState } from 'react';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, setMyList] = useState(initialList);
  const [yourList, setYourList] = useState(
    initialList
  );

  function handleToggleMyList(artworkId, nextSeen) {
    const myNextList = [...myList];
    const artwork = myNextList.find(
      a => a.id === artworkId
    );
    artwork.seen = nextSeen;
    setMyList(myNextList);
  }

  function handleToggleYourList(artworkId, nextSeen) {
    const yourNextList = [...yourList];
    const artwork = yourNextList.find(
      a => a.id === artworkId
    );
    artwork.seen = nextSeen;
    setYourList(yourNextList);
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Your list of art to see:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

ๅ•้กŒใฏใ“ใฎใ‚ณใƒผใƒ‰ใงใ™ใ€‚

const myNextList = [...myList];
const artwork = myNextList.find(a => a.id === artworkId);
artwork.seen = nextSeen; // Problem: mutates an existing item
setMyList(myNextList);

myNextList ใจใ„ใ†้…ๅˆ—่‡ชไฝ“ใฏๆ–ฐใ—ใ„ใ‚‚ใฎใงใ™ใŒใ€ๅ€‹ใ€…ใฎ่ฆ็ด ใใฎใ‚‚ใฎใฏๅ…ƒใฎ myList ้…ๅˆ—ใจๅŒใ˜ใงใ™ใ€‚ใใฎใŸใ‚ใ€artwork.seen ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใงใ€ๅ…ƒใฎใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใ‚‚ๅค‰ๆ›ดใ•ใ‚Œใพใ™ใ€‚ใใฎใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใฏ yourList ๅ†…ใซใ‚‚ๅญ˜ๅœจใ™ใ‚‹ใŸใ‚ใ€ใƒใ‚ฐใŒ็™บ็”Ÿใ—ใพใ™ใ€‚ใ“ใฎใ‚ˆใ†ใชใƒใ‚ฐใฏ็†่งฃใ™ใ‚‹ใฎใŒ้›ฃใ—ใ„ใ“ใจใŒใ‚ใ‚Šใพใ™ใŒใ€ๅนธใ„ใซใ‚‚ state ใฎใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใ•ใˆ้ฟใ‘ใฆใŠใ‘ใฐใ€่ตทใ“ใ•ใšใซๆธˆใฟใพใ™ใ€‚

ใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ใ›ใšใซใ€ๅคใ„่ฆ็ด ใ‚’ๆ›ดๆ–ฐใ•ใ‚ŒใŸ่ฆ็ด ใจ็ฝฎใๆ›ใˆใ‚‹ใซใฏใ€map ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚

setMyList(myList.map(artwork => {
if (artwork.id === artworkId) {
// Create a *new* object with changes
return { ...artwork, seen: nextSeen };
} else {
// No changes
return artwork;
}
}));

ใ“ใ“ใงใ€... ใฏใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใงใ‚ใ‚Šใ€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚

ใ“ใฎใ‚ขใƒ—ใƒญใƒผใƒใงใฏใ€ๆ—ขๅญ˜ใฎ state ใฎ่ฆ็ด ใ‚’ๆ›ธใๆ›ใˆใชใ„ใŸใ‚ใ€ใƒใ‚ฐใฏไฟฎๆญฃใ•ใ‚Œใฆใ„ใพใ™ใ€‚

import { useState } from 'react';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, setMyList] = useState(initialList);
  const [yourList, setYourList] = useState(
    initialList
  );

  function handleToggleMyList(artworkId, nextSeen) {
    setMyList(myList.map(artwork => {
      if (artwork.id === artworkId) {
        // Create a *new* object with changes
        return { ...artwork, seen: nextSeen };
      } else {
        // No changes
        return artwork;
      }
    }));
  }

  function handleToggleYourList(artworkId, nextSeen) {
    setYourList(yourList.map(artwork => {
      if (artwork.id === artworkId) {
        // Create a *new* object with changes
        return { ...artwork, seen: nextSeen };
      } else {
        // No changes
        return artwork;
      }
    }));
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Your list of art to see:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

ไธ€่ˆฌ็š„ใซใฏใ€ไฝœๆˆใ—ใŸใฐใ‹ใ‚Šใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆไปฅๅค–ใฏๆ›ธใๆ›ใˆใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ๆ–ฐใ—ใ„ใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใ‚’ๆŒฟๅ…ฅใ™ใ‚‹ๅ ดๅˆใซใใฎๆ–ฐใ—ใ„่ฆ็ด ใ‚’ๆ›ธใๆ›ใˆใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใŒใ€state ใซใ™ใงใซๅญ˜ๅœจใ™ใ‚‹ใ‚‚ใฎใ‚’ๆ‰ฑใ†ๅ ดๅˆใฏใ€ใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

Immer ใ‚’ไฝฟใฃใฆ็ฐกๆฝ”ใชๆ›ดๆ–ฐใƒญใ‚ธใƒƒใ‚ฏใ‚’ๆ›ธใ

้…ๅˆ—ใŒใƒใ‚นใƒˆใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ๆ›ธใๆ›ใˆใชใ—ใงๆ›ดๆ–ฐใ‚’่กŒใ†ใ‚ณใƒผใƒ‰ใฏๅ†—้•ทใซใชใ‚ŠใŒใกใงใ™ใ€‚ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใจใใจๅŒๆง˜ใงใ™ใŒใ€

  • ไธ€่ˆฌ็š„ใซใฏใ€state ใ‚’ 2ใ€œ3 ใƒฌใƒ™ใƒซไปฅไธŠๆทฑใๆ›ดๆ–ฐใ™ใ‚‹ๅฟ…่ฆใฏใชใ„ใฏใšใงใ™ใ€‚state ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒ้žๅธธใซๆทฑใ„ๅ ดๅˆใฏใ€ๅˆฅใฎๆง‹้€ ใซๅ†ๆง‹ๆˆใ—ใฆใƒ•ใƒฉใƒƒใƒˆใซใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚
  • state ๆง‹้€ ใ‚’ๅค‰ๆ›ดใ—ใŸใใชใ„ๅ ดๅˆใฏใ€Immer ใ‚’ไฝฟ็”จใ—ใฆใ€ๆ›ธใใ‚„ใ™ใ„ใƒŸใƒฅใƒผใƒ†ใƒผใƒˆๅž‹ใฎๆง‹ๆ–‡ใง่จ˜่ฟฐใ—ใคใคใ‚ณใƒ”ใƒผใ‚’็”Ÿๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚

ไปฅไธ‹ใฏใ€Immer ใ‚’ไฝฟ็”จใ—ใฆๆ›ธใ็›ดใ—ใŸใ‚ขใƒผใƒˆใƒฏใƒผใ‚ฏใƒชใ‚นใƒˆใฎไพ‹ใงใ™ใ€‚

{
  "dependencies": {
    "immer": "1.7.3",
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "use-immer": "0.5.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Immer ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใง artwork.seen = nextSeen ใฎใ‚ˆใ†ใชๆ›ธใๆ›ใˆใŒใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚

updateMyTodos(draft => {
const artwork = draft.find(a => a.id === artworkId);
artwork.seen = nextSeen;
});

ใ“ใ‚ŒใŒๅฏ่ƒฝใชใฎใฏใ€Immer ใ‹ใ‚‰ๆธกใ•ใ‚Œใ‚‹็‰นๅˆฅใช draft ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ›ธใๆ›ใˆใฆใ„ใ‚‹ใฎใงใ‚ใ‚Šใ€ๅ…ƒใฎ state ใฏๆ›ธใๆ›ใˆใฆใ„ใชใ„ใŸใ‚ใงใ™ใ€‚ๅŒๆง˜ใซใ€draft ใฎๅ†…ๅฎนใซๅฏพใ—ใฆ push() ใ‚„ pop() ใชใฉใฎใƒŸใƒฅใƒผใƒ†ใƒผใ‚ทใƒงใƒณๅž‹ใฎใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚

่ฃๅดใงใฏใ€Immer ใฏๅธธใซใ€draft ใซๅฏพใ—ใฆ่กŒใฃใŸๆ›ธใๆ›ใˆๆ“ไฝœใซๅŸบใฅใ„ใฆใ€ๆฌกใฎ state ใ‚’ใ‚ผใƒญใ‹ใ‚‰ๆง‹็ฏ‰ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€state ใ‚’ๆ›ธใๆ›ใˆใฆใ—ใพใ†ๅฟƒ้…ใ‚’ใ›ใšใ€ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉใ‚’้žๅธธใซ็ฐกๆฝ”ใซไฟใคใ“ใจใŒใงใใพใ™ใ€‚

ใพใจใ‚

  • ้…ๅˆ—ใ‚’ state ใซๅ…ฅใ‚Œใ‚‹ใ“ใจใŒใงใใ‚‹ใŒใ€ใใ‚Œใ‚’็›ดๆŽฅๅค‰ๆ›ดใ—ใฆใฏใ„ใ‘ใชใ„ใ€‚
  • ้…ๅˆ—ใ‚’ๅค‰ๆ›ดใ›ใšใ€ไปฃใ‚ใ‚Šใซๆ–ฐใ—ใ„็‰ˆใ‚’ไฝœๆˆใ—ใ€state ใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ€‚
  • [...arr, newItem] ใจใ„ใ†้…ๅˆ—ใ‚นใƒ—ใƒฌใƒƒใƒ‰ๆง‹ๆ–‡ใ‚’ไฝฟ็”จใ—ใฆใ€ๆ–ฐใ—ใ„้ …็›ฎใ‚’ๆŒใค้…ๅˆ—ใ‚’ไฝœๆˆใงใใ‚‹ใ€‚
  • filter() ใ‚„ map() ใ‚’ไฝฟ็”จใ—ใฆใ€ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ•ใ‚ŒใŸใ€ใ‚ใ‚‹ใ„ใฏๅค‰ๆ›ใ•ใ‚ŒใŸใ‚ขใ‚คใƒ†ใƒ ใ‚’ๅซใ‚€ๆ–ฐใ—ใ„้…ๅˆ—ใ‚’ไฝœๆˆใงใใ‚‹ใ€‚
  • Immer ใ‚’ไฝฟใฃใฆใ‚ณใƒผใƒ‰ใ‚’็ฐกๆฝ”ใซไฟใคใ“ใจใŒใงใใ‚‹ใ€‚

ใƒใƒฃใƒฌใƒณใ‚ธ 1/4:
ใ‚ทใƒงใƒƒใƒ”ใƒณใ‚ฐใ‚ซใƒผใƒˆใฎๅ•†ๅ“ใ‚’ๆ›ดๆ–ฐ

handleIncreaseClick ใฎใƒญใ‚ธใƒƒใ‚ฏใ‚’ๅŸ‹ใ‚ใฆใ€โ€+โ€ ใ‚’ๆŠผใ™ใ“ใจใงๅฏพๅฟœใ™ใ‚‹ๆ•ฐๅญ—ใŒๅข—ใˆใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚

import { useState } from 'react';

const initialProducts = [{
  id: 0,
  name: 'Baklava',
  count: 1,
}, {
  id: 1,
  name: 'Cheese',
  count: 5,
}, {
  id: 2,
  name: 'Spaghetti',
  count: 2,
}];

export default function ShoppingCart() {
  const [
    products,
    setProducts
  ] = useState(initialProducts)

  function handleIncreaseClick(productId) {

  }

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name}
          {' '}
          (<b>{product.count}</b>)
          <button onClick={() => {
            handleIncreaseClick(product.id);
          }}>
            +
          </button>
        </li>
      ))}
    </ul>
  );
}