Как правильно обновлять массив, чтобы при нажатии кнопки на странице в него добавлялся новый элемент?

<pre><code class="html">&lt;!doctype html&gt;
  • 12 апреля 2026 г. 17:00
Ответы на вопрос 4
Нужен контекст — вы работаете в чистом JS, в React, Vue или другом фреймворке? Ниже приведены короткие правильные способы для самых распространённых случаев.

1) Чистый JavaScript (DOM)
- В обычном JS можно использовать push и затем обновлять отображение (перерисовать список).
Пример:
```
<!doctype html>
<html>
<body>
  <button id="add">Добавить</button>
  <ul id="list"></ul>

  <script>
    const arr = [];
    const btn = document.getElementById('add');
    const list = document.getElementById('list');

    function render() {
      list.innerHTML = '';
      arr.forEach(item => {
        const li = document.createElement('li');
        li.textContent = item;
        list.appendChild(li);
      });
    }

    btn.addEventListener('click', () => {
      const newItem = 'Элемент ' + (arr.length + 1);
      arr.push(newItem); // добавляем
      render(); // обновляем DOM
    });
  </script>
</body>
</html>
```

2) React (функциональные компоненты, useState) — самый частый источник вопросов
- Не мутируйте состояние напрямую (не делайте arr.push(state)). Вместо этого создайте новый массив:
```
import React, { useState } from 'react';

function App() {
  const [items, setItems] = useState([]);

  const addItem = () => {
    const newItem = 'Item ' + (items.length + 1);
    // корректный способ — создать новый массив
    setItems(prev => [...prev, newItem]);
  };

  return (
    <>
      <button onClick={addItem}>Добавить</button>
      <ul>
        {items.map((it, i) => <li key={i}>{it}</li>)}
      </ul>
    </>
  );
}
```
Почему так: React отслеживает изменение ссылки на массив; если мутировать старый массив (push) без создания новой ссылки, React может не перерисовать компонент.

3) React (классовый компонент)
```
this.setState(prev => ({
  items: [...prev.items, newItem]
}));
```

4) Vue 3 (Composition API)
- Vue корректно отслеживает изменения в массивах при push, но безопаснее работать с reactive/ref:
```
import { ref } from 'vue';
const items = ref([]);
function add() {
  items.value.push('new');
}
```
В Vue 2 также push обычно работает и реактивен.

Полезные замечания:
- В React всегда создавайте новый объект/массив при обновлении состояния (immutability).
- При рендеринге списка ставьте уникальный key (не индекс, если порядок меняется).
- Если добавление зависит от предыдущего состояния — используйте функцию в setState (prev => ...), чтобы избежать гонок.
- Генерируйте уникальные id для элементов (например uuid или счётчик), если нужен стабильный key.

Если скажете, в какой среде/фреймворке вы работаете и покажете ваш код, я дам точную правку.
заменить <pre><code class="javascript">let arr = [
  'Мастер и Маргарита',
...
];</code></pre> на <pre><code class="javascript">let arr = [
  {title: 'Мастер и Маргарита', el: null},
...
];</code></pre> и вместо безусловного создания элемента - проверять его существование и обновлять содержимое при необходимости
каждый вызов renderList создаёт новый <ul> и докидывает его в body — отсюда и стопка списков. выноси listEl наружу и удаляй перед рендером: <br/> <br/> <pre><code>let listEl;

function renderList(arr) {
  if (listEl) listEl.remove();
  listEl = document.createElement('ul');
  for (let i = 0; i &amp;lt; arr.length; i++) {
    const liEl = document.createElement('li');
    liEl.textContent = `${i + 1}) ${arr[i]}`;
    listEl.append(liEl);
  }
  document.body.append(listEl);
}</code></pre> <br/> <br/> или вместо перерисовки всего списка — добавляй только один новый li к уже существующему.
1. весь html вынести в html. <br/> 2. Проверять существование списка, даже если вы не вынесли html из js. <br/> 3. Либо стерать элементы из ul, либо просто в конец добавлять новый элемент в ul.
Похожие вопросы