Не срабатывает onClick внутри таблицы. React

Пишу приложение на React, которое-по API принимает данные для таблицы и выводит их. Среди прочего функционала, в заглавных ячейках колонок(столбцов ) должна быть кнопка для удаления этого самого столбца.

Столкнулся со следующей проблемой: событие onClick не срабатывает внутри ячейки, но срабатывает вне таблицы. Что делаю не так, и как заставить кнопку внутри th - отзываться ?

import React from 'react';
import './App.css';

function App() {

  const [items, setItems] = React.useState([]);

  React.useEffect(() => {
    fetch('https://example.com/')
      .then((resp) => resp.json())
      .then(json => {
        setItems(json.data)
      })
  }, []);

  const addItem = () => {
    let list = document.querySelector('.items')

    let key;

    for (key in items) {
      list.innerHTML += `
        <tr>
          <td>${items[key].id}</td>
          <td>${items[key].year}</td>
        </tr>
        `
    }
  }

  addItem();

  const del = () => {
    console.log('test')
  }

  return (
    <div className="mainContainer">

      <span className="tableHeader">
        <h1 onClick={del}>Pantone Colors</h1>
        //Эта кнопка работает правильно

        <p>Reset</p>
      </span>
      <table className="table">
        <tbody className='items'>
          <tr >
            <th><input type="checkbox" defaultChecked />id</th>
            <th><input type="checkbox" defaultChecked />year <button onClick={del}>Delete</button> </th>
            //Эта кнопка не работает

          </tr>
        </tbody>
      </table>
    </div >
  );
}

export default App;

Ответы (1 шт):

Автор решения: Август

теоретически, проблема из-за innerHTML. innerHTML не надо использовать в React. я бы даже сказал, что это противопоказано


import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [tableItems, setTableItems] = useState([]); // контент всех ячеек выносим в state

  useEffect(() => {
    (async () => {
      let response = await fetch('https://example.com/');
      let content = await response.json();
      setTableItems([...tableItems, ...content]); // когда получили ответ из запроса, записываем его в state
    })();
  }, []);

  const del = () => console.log('test');

  return (
    <div className="mainContainer">
      <span className="tableHeader">
        <h1 onClick={del}>Pantone Colors</h1>
        <p>Reset</p>
      </span>
      <table className="table">
        <tbody className='items'>
          <tr >
            <th><input type="checkbox" defaultChecked />id</th>
            <th><input type="checkbox" defaultChecked />name</th>
            <th onClick={del}><input type="checkbox" defaultChecked />year </th>
          </tr>
          {
            !!tableItems.length && // проверяем есть ли хоть что-то в tableItems
            tableItems.map(item => ( // если есть, то перебираем весь массив и отрисовываем каждую ячейку. но лучше какждую ячейку вынести как отдельный компонент
              <tr key={item.id}>
                <td>${item.id}</td>
                <td>${item.name}</td>
                <td>${item.year}</td>
                <td>
                  <div className="itemColor" style="
                    width: 10px;
                    height: 10px;
                    border-radius: 3px;
                    background-color: ${content.data[key].color};
                    display: inline-flex;">
                  </div> 
                  ${item.color}
                </td>
                <td>${item.pantone_value}</td>
              </tr>
            ))
          }
        </tbody>
      </table>
    </div >
  );
}

export default App;
→ Ссылка