react — превышена максимальная глубина обновления с использованием react-table

#javascript #reactjs #react-native

#javascript #reactjs #react-native

Вопрос:

Попытка включить react-table в базовое приложение, которое принимает входные данные в поле, сохраняет их в состоянии компонентов при изменении содержимого поля, а затем извлекает данные из Github нажатием кнопки.

Все работает нормально, пока я не добавлю строку

const tableInstance = useTable({columns, data})

Страница будет загружаться нормально, но в тот момент, когда поле ввода изменяется (т. Е. вы вводите его), приложение вылетает с ошибкой:

Ошибка: Превышена максимальная глубина обновления. Это может произойти, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений, чтобы предотвратить бесконечные циклы.

Трассировка стека включает эти фрагменты из библиотеки react-table

hooks/useColumnVisibility.js

   204 | 
  205 | useMountedLayoutEffect(() => {
  206 |   if (getAutoResetHiddenColumns()) {
> 207 |     dispatch({ type: actions.resetHiddenColumns })
  208 | ^ }
  209 | }, [dispatch, columns])
  210 | 
  

и publicUtils.js:

   153 | 
  154 | safeUseLayoutEffect(() => {
  155 |   if (mountedRef.current) {
> 156 |     fn()
  157 | ^ }
  158 |   mountedRef.current = true
  159 |   // eslint-disable-next-line
  

Это код из моего App.js файл

 import React, { useState } from 'react';
import './App.css';
import {useTable} from "react-table"

function App() {

  const [data, setData] = useState([]);
  const [keyword, setKeyword] = useState('');

  const fetchData = () => {
    const url = `https://api.github.com/search/repositories?q=${keyword}`
    fetch(url)
      .then(response => response.json())
      .then(responseData => {
        setData(responseData.items);
      });
  }

  const handleChange = (e) => {
    setKeyword(e.target.value);
  }

  const columns = [{
    Header: 'Name', //column header 
    accessor: 'full_name' //Value accessor
  }, {
    Header: 'URL',
    accessor: 'html_url'
  }, {
    Header: 'Owner',
    accessor: 'owner.login'
  }]

  const tableInstance = useTable({columns, data}) // line causing the problem

  return (
    <div className="App">
      <input type="text" onChange={handleChange}/>
      <button onClick={fetchData} value={keyword} >Fetch</button>
    </div>
  );
}

export default App;
  

Предположительно, я сделал что-то, что заставляет состояние обновляться каждый раз при рендеринге страницы, тем самым вызывая другой рендеринг, но я не могу понять, что это такое. Заранее спасибо за любую помощь.

Ответ №1:

Хорошо, итак, я исправил это, создав компонент Table, который затем включается в DOM компонента приложения.

Это обновленный код, который устраняет проблему

 import React, { useState } from 'react';
import './App.css';
import {useTable} from "react-table"

function Table({columns, data}){

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
  } = useTable({columns, data})

  return (
    <table {...getTableProps()}>
      <thead>
        {
          headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {
                  headerGroup.headers.map( column => (
                    <th {...column.getHeaderProps()}>
                      {
                        column.render('Header')
                      }
                    </th>
                  ))
                }
              </tr>
          ))
        }
      </thead>
      <tbody {...getTableBodyProps()}>
        { // loop over the rows
          rows.map(row => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                { // loop over the rows cells 
                  row.cells.map(cell => (
                    <td {...cell.getCellProps()}>
                      {cell.render('Cell')}
                    </td>
                  ))
                }
              </tr> 
            )
          })
        }
        <tr>
          <td></td>
        </tr>
      </tbody>
    </table>
  );
}

function App() {

  const [data, setData] = useState([]);
  const [keyword, setKeyword] = useState('');

  const fetchData = () => {
    const url = `https://api.github.com/search/repositories?q=${keyword}`
    fetch(url)
      .then(response => response.json())
      .then(responseData => {
        setData(responseData.items);
      });
  }

  const handleChange = (e) => {
    setKeyword(e.target.value);
  }

  const columns = [{
    Header: 'Name', //column header 
    accessor: 'full_name' //Value accessor
  }, {
    Header: 'URL',
    accessor: 'html_url'
  }, {
    Header: 'Owner',
    accessor: 'owner.login'
  }]


  return (
    <div className="App">
      <input type="text" onChange={handleChange}/>
      <button onClick={fetchData} value={keyword} >Fetch</button>
      <Table 
        columns={columns} 
        data = {data}
      />
    </div>
  );
}

export default App;
  

Проблема в том, что я действительно не знаю, почему это работает или в чем суть проблемы была в первую очередь.

Комментарии:

1. Эта проблема с GitHub может пролить некоторый свет на проблему: github.com/tannerlinsley/react-table/issues/2369

2. У меня ничего из этого не сработало. Наконец, настройка autoResetHiddenColumns: false решила проблему.

3. У меня была похожая проблема: у меня есть приложение react с маршрутизатором, и когда я пытался вызвать useState внутри маршрутизируемого компонента, я получал сообщение об ошибке о настройке состояния несколько раз или что-то в этом роде, поэтому вместо вызова useTable перехвата моего корневого компонента я добавил его в компонент, который создал таблицу

4. @ixaxaar Ваш метод работает для меня.