Thay đổi giá trị trong mảng đối tượng javascript

Mảng có thể thay đổi trong JavaScript, nhưng bạn nên coi chúng là bất biến khi bạn lưu trữ chúng ở trạng thái. Cũng giống như với các đối tượng, khi bạn muốn cập nhật một mảng được lưu trữ trong trạng thái, bạn cần tạo một mảng mới (hoặc tạo một bản sao của mảng hiện có), sau đó thiết lập trạng thái để sử dụng mảng mới

Bạn sẽ học

  • Cách thêm, xóa hoặc thay đổi các mục trong một mảng ở trạng thái React
  • Cách cập nhật một đối tượng bên trong một mảng
  • Cách sao chép mảng ít lặp lại hơn với Immer

Cập nhật mảng mà không có đột biến

Trong JavaScript, mảng chỉ là một loại đối tượng khác. Giống như với các đối tượng, bạn nên coi các mảng ở trạng thái React là chỉ đọc. Điều này có nghĩa là bạn không nên gán lại các mục bên trong một mảng như

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

]

);

8 và bạn cũng không nên sử dụng các phương thức làm thay đổi mảng, chẳng hạn như

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

]

);

9 và
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

0

Thay vào đó, mỗi khi bạn muốn cập nhật một mảng, bạn sẽ muốn chuyển một mảng mới vào hàm cài đặt trạng thái của mình. Để làm điều đó, bạn có thể tạo một mảng mới từ mảng ban đầu ở trạng thái của mình bằng cách gọi các phương thức không thay đổi của nó như

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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

1 và
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

2. Sau đó, bạn có thể đặt trạng thái của mình thành mảng mới kết quả

Đây là một bảng tham chiếu của hoạt động mảng phổ biến. Khi xử lý các mảng bên trong trạng thái React, bạn sẽ cần tránh các phương thức ở cột bên trái và thay vào đó hãy ưu tiên các phương thức ở cột bên phải

tránh (biến đổi mảng)thích (trả về một mảng mới)thêm_______2_______3,
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

4_______2_______5,
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

6 cú pháp lây lan ()loại bỏ
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

7,
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

8,
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

9

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

0,

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

1 ()thay thế
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

9,

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

3 bài tập

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4 ()sắp xếp_______12_______5,

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

6 trước tiên ()

Ngoài ra, bạn có thể cho phép bạn sử dụng các phương thức từ cả hai cột

cạm bẫy

Thật không may,

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

1 và
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

9 được đặt tên giống nhau nhưng lại rất khác nhau

  • setArtists([

    { id: nextId++, name: name },

    ...artists // Put old items at the end

    ]);

    1 cho phép bạn sao chép một mảng hoặc một phần của nó
  • 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={() => {
            setName('');
            setArtists([
              ...artists,
              { id: nextId++, name: name }
            ]);
          }}>Addbutton>
          <ul>
            {artists.map(artist => (
              <li key={artist.id}>{artist.name}li>
            ))}
          ul>
        >
      );
    }
    
    
    9 thay đổi mảng (để chèn hoặc xóa các mục)

Trong React, bạn sẽ sử dụng

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

1 (không có
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>
    >
  );
}

2. ) thường xuyên hơn vì bạn không muốn thay đổi đối tượng hoặc mảng trong trạng thái. Cập nhật đối tượng giải thích đột biến là gì và tại sao nó không được khuyến nghị cho trạng thái

Thêm vào một mảng

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

]

);

9 sẽ biến đổi một mảng mà bạn không muốn

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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={() => {
        setName('');
        artists.push({
          id: nextId++,
          name: name,
        });
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

Cho xem nhiều hơn

Thay vào đó, hãy tạo một mảng mới chứa các mục hiện có và một mục mới ở cuối. Có nhiều cách để làm điều này, nhưng cách dễ nhất là sử dụng cú pháp

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

4

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

]

);

Bây giờ nó hoạt động chính xác

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

Cho xem nhiều hơn

Cú pháp dàn trải mảng cũng cho phép bạn thêm vào trước một mục bằng cách đặt nó trước bản gốc

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

5

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

Theo cách này, spread có thể thực hiện công việc của cả

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

]

);

9 bằng cách thêm vào cuối mảng và
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>
    >
  );
}

7 bằng cách thêm vào đầu mảng. Hãy thử nó trong hộp cát ở trên

Loại bỏ khỏi một mảng

Cách dễ nhất để xóa một mục khỏi mảng là lọc nó ra. Nói cách khác, bạn sẽ tạo ra một mảng mới không chứa mục đó. Để làm điều này, hãy sử dụng phương pháp

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

0, ví dụ

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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

Cho xem nhiều hơn

Nhấp vào nút "Xóa" một vài lần và xem trình xử lý nhấp chuột của nó

setArtists(

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

);

Ở đây,

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

9 có nghĩa là “tạo một mảng bao gồm những

setArtists(

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

);

0 có ID khác với

setArtists(

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

);

1”. Nói cách khác, nút “Xóa” của mỗi nghệ sĩ sẽ lọc nghệ sĩ đó ra khỏi mảng, sau đó yêu cầu kết xuất lại với mảng kết quả. Lưu ý rằng

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

0 không sửa đổi mảng ban đầu

Chuyển đổi một mảng

Nếu bạn muốn thay đổi một số hoặc tất cả các phần tử của mảng, bạn có thể sử dụng

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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

2 để tạo một mảng mới. Hàm mà bạn sẽ chuyển đến

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4 có thể quyết định phải làm gì với từng mục, dựa trên dữ liệu hoặc chỉ mục của mục đó (hoặc cả hai)

Trong ví dụ này, một mảng chứa tọa độ của hai hình tròn và hình vuông. Khi bạn nhấn nút, nó chỉ di chuyển các vòng tròn xuống 50 pixel. Nó thực hiện điều này bằng cách tạo ra một mảng dữ liệu mới bằng cách sử dụng

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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

2

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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

Cho xem nhiều hơn

Thay thế các mục trong một mảng

Việc muốn thay thế một hoặc nhiều phần tử trong một mảng là điều đặc biệt phổ biến. Các phép gán như

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

]

);

8 đang thay đổi mảng ban đầu, vì vậy, thay vào đó, bạn cũng sẽ muốn sử dụng

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4 cho việc này

Để thay thế một mục, hãy tạo một mảng mới với

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4. Trong cuộc gọi

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4 của bạn, bạn sẽ nhận được chỉ mục mục làm đối số thứ hai. Sử dụng nó để quyết định trả lại mục ban đầu (đối số đầu tiên) hay cái gì khác

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

Cho xem nhiều hơn

Chèn vào một mảng

Đôi khi, bạn có thể muốn chèn một mục vào một vị trí cụ thể không phải ở đầu cũng không phải ở cuối. Để làm điều này, bạn có thể sử dụng cú pháp trải rộng mảng

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

4 cùng với phương thức
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,
        }} />
      ))}
    >
  );
}

1. Phương thức
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,
        }} />
      ))}
    >
  );
}

1 cho phép bạn cắt một “lát cắt” của mảng. Để chèn một mục, bạn sẽ tạo một mảng trải rộng lát cắt trước điểm chèn, sau đó là mục mới và sau đó là phần còn lại của mảng ban đầu

Trong ví dụ này, nút Chèn luôn chèn tại chỉ mục

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

3

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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

Cho xem nhiều hơn

Thực hiện các thay đổi khác đối với một mảng

Có một số điều bạn không thể làm với cú pháp trải rộng và các phương pháp không biến đổi như chỉ riêng

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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

2 và
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

1. Ví dụ: bạn có thể muốn đảo ngược hoặc sắp xếp một mảng. Các phương thức
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,
        }} />
      ))}
    >
  );
}

6 và
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,
        }} />
      ))}
    >
  );
}

7 của JavaScript đang thay đổi mảng ban đầu, vì vậy bạn không thể sử dụng chúng trực tiếp

Tuy nhiên, bạn có thể sao chép mảng trước rồi thực hiện các thay đổi đối với mảng đó

Ví dụ

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

import { useState } from 'react';

let nextId = 3;
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>
    >
  );
}

Cho xem nhiều hơn

Ở đây, bạn sử dụng cú pháp trải rộng

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

8 để tạo một bản sao của mảng ban đầu trước. Bây giờ bạn đã có một bản sao, bạn có thể sử dụng các phương pháp biến đổi như
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,
        }} />
      ))}
    >
  );
}

9 hoặc
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

0 hoặc thậm chí chỉ định các mục riêng lẻ với
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

1

Tuy nhiên, ngay cả khi bạn sao chép một mảng, bạn không thể trực tiếp thay đổi các mục hiện có bên trong mảng đó. Điều này là do quá trình sao chép còn nông—mảng mới sẽ chứa các mục giống như mảng ban đầu. Vì vậy, nếu bạn sửa đổi một đối tượng bên trong mảng đã sao chép, bạn đang thay đổi trạng thái hiện có. Ví dụ, mã như thế này là một vấn đề

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

]

);

0

Mặc dù

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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

2 và
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

3 là hai mảng khác nhau, nhưng
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

4 và
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

5 trỏ đến cùng một đối tượng. Vì vậy, bằng cách thay đổi
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

6, bạn cũng đang thay đổi
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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

7. Đây là một đột biến trạng thái, mà bạn nên tránh. Bạn có thể giải quyết vấn đề này theo cách tương tự —bằng cách sao chép các mục riêng lẻ mà bạn muốn thay đổi thay vì thay đổi chúng. Đây là cách

Cập nhật các đối tượng bên trong mảng

Các đối tượng không thực sự nằm trong các mảng bên trong. Chúng có thể xuất hiện "bên trong" trong mã, nhưng mỗi đối tượng trong một mảng là một giá trị riêng biệt, mà mảng "chỉ" tới. Đây là lý do tại sao bạn cần cẩn thận khi thay đổi các trường lồng nhau như

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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

5. Danh sách tác phẩm nghệ thuật của người khác có thể trỏ đến cùng một phần tử của mảng

Khi cập nhật trạng thái lồng nhau, bạn cần tạo các bản sao từ điểm bạn muốn cập nhật và cho đến cấp cao nhất. Hãy xem cách nó hoạt động

Trong ví dụ này, hai danh sách tác phẩm nghệ thuật riêng biệt có cùng trạng thái ban đầu. Chúng được cho là bị cô lập, nhưng do đột biến, trạng thái của chúng vô tình bị chia sẻ và việc chọn một hộp trong một danh sách sẽ ảnh hưởng đến danh sách kia

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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

]

);

1

Cho xem nhiều hơn

Vấn đề là trong mã như thế này

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

]

);

2

Mặc dù bản thân mảng

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);
          }}>+1button>
        li>
      ))}
    ul>
  );
}

9 là mới, nhưng bản thân các phần tử vẫn giống như trong mảng
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>
    >
  );
}

0 ban đầu. Vì vậy, việc thay đổi
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>
    >
  );
}

1 sẽ thay đổi mục tác phẩm nghệ thuật gốc. Tác phẩm nghệ thuật đó cũng nằm trong
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>
    >
  );
}

2, gây ra lỗi. Những lỗi như thế này có thể khó nghĩ đến, nhưng may mắn là chúng sẽ biến mất nếu bạn tránh trạng thái đột biến

Bạn có thể sử dụng

setArtists([

{ id: nextId++, name: name },

...artists // Put old items at the end

]);

4 để thay thế một mục cũ bằng phiên bản cập nhật của nó mà không bị thay đổi

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

]

);

3

Ở đây,

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

4 là cú pháp lây lan đối tượng được sử dụng để

Với phương pháp này, không có mục trạng thái hiện có nào bị thay đổi và lỗi đã được sửa

Ứng dụng. js

Ứng dụng. js

Đặt lại Ngã ba

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

]

);

4

Cho xem nhiều hơn

Nói chung, bạn chỉ nên thay đổi các đối tượng mà bạn vừa tạo. Nếu bạn đang chèn một tác phẩm nghệ thuật mới, bạn có thể thay đổi nó, nhưng nếu bạn đang xử lý thứ gì đó đã có sẵn, bạn cần tạo một bản sao

Viết logic cập nhật ngắn gọn với Immer

Cập nhật các mảng lồng nhau mà không có đột biến có thể hơi lặp lại.

  • Nói chung, bạn không cần cập nhật trạng thái nhiều hơn một vài cấp độ. Nếu các đối tượng trạng thái của bạn rất sâu, bạn có thể muốn sao cho chúng bằng phẳng
  • Nếu bạn không muốn thay đổi cấu trúc trạng thái của mình, bạn có thể thích sử dụng Immer hơn, cho phép bạn viết bằng cú pháp thuận tiện nhưng có thể thay đổi và đảm nhiệm việc tạo các bản sao cho bạn

Đây là ví dụ về Art Bucket List được viết lại bằng Immer

Ứng dụng. gói js. json

Ứng dụng. js

Đặt lại Ngã ba

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

]

);

5

Cho xem nhiều hơn

Lưu ý cách với Immer, đột biến như

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

5 hiện không sao

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

]

);

6

Điều này là do bạn không thay đổi trạng thái ban đầu, nhưng bạn đang thay đổi một đối tượng

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

6 đặc biệt do Immer cung cấp. Tương tự, bạn có thể áp dụng các phương pháp biến đổi như

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

]

);

9 và
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={() => {
        setName('');
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Addbutton>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}li>
        ))}
      ul>
    >
  );
}

0 cho nội dung của
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>
    >
  );
}

6

Đằng sau hậu trường, Immer luôn xây dựng trạng thái tiếp theo từ đầu theo những thay đổi mà bạn đã thực hiện đối với

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

6. Điều này giữ cho trình xử lý sự kiện của bạn rất ngắn gọn mà không bao giờ thay đổi trạng thái

Tóm tắt lại

  • Bạn có thể đặt mảng vào trạng thái, nhưng bạn không thể thay đổi chúng
  • Thay vì thay đổi một mảng, hãy tạo một phiên bản mới của nó và cập nhật trạng thái cho nó
  • Bạn có thể sử dụng cú pháp trải rộng mảng
    import { useState } from 'react';
    
    let nextId = 3;
    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>
        >
      );
    }
    
    
    1 để tạo mảng với các mục mới
  • Bạn có thể sử dụng
    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={() => {
            setName('');
            setArtists([
              ...artists,
              { id: nextId++, name: name }
            ]);
          }}>Addbutton>
          <ul>
            {artists.map(artist => (
              <li key={artist.id}>{artist.name}li>
            ))}
          ul>
        >
      );
    }
    
    
    1 và
    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={() => {
            setName('');
            setArtists([
              ...artists,
              { id: nextId++, name: name }
            ]);
          }}>Addbutton>
          <ul>
            {artists.map(artist => (
              <li key={artist.id}>{artist.name}li>
            ))}
          ul>
        >
      );
    }
    
    
    2 để tạo mảng mới với các mục được lọc hoặc biến đổi
  • Bạn có thể sử dụng Immer để giữ cho mã của bạn ngắn gọn

Hãy thử một số thử thách

1. Cập nhật một mặt hàng trong giỏ hàng2. Xóa một mặt hàng khỏi giỏ hàng3. Sửa các đột biến bằng các phương pháp không đột biến4. Sửa các đột biến bằng cách sử dụng Immer

Làm cách nào để cập nhật giá trị trong mảng đối tượng JavaScript?

Để cập nhật một đối tượng trong một mảng JavaScript, bạn có thể sử dụng phương thức findIndex() để thực thi từng phần tử mảng và cập nhật các giá trị đối tượng tương ứng .

Làm cách nào để thay đổi giá trị trong đối tượng JavaScript?

Để cập nhật tất cả các giá trị trong một đối tượng, cách dễ nhất là. .
Sử dụng đối tượng. keys để lấy tất cả các key của đối tượng
Áp dụng bất kỳ logic nào để quyết định giá trị nào sẽ được cập nhật
Cập nhật giá trị của từng giá trị bằng vòng lặp như forEach hoặc for