Infinite rerender loop triggered with controlled Spreadsheet
Reproducer:
yarn create vite spreadsheet-repro --template react-ts
yarn add scheduler react-spreadsheet
yarn
yarn dev
Then replace the code in App.tsx with the following:
const [data, setData] = useState([
[{ value: "Vanilla" }, { value: "Chocolate" }, { value: "" }],
[{ value: "Strawberry" }, { value: "Cookies" }, { value: "" }],
]);
const setDataWrapper = (data) => {
console.log("setting data")
setData(data)
}
return (
<Spreadsheet data={data} onChange={setDataWrapper} />
)
Start editing cells and the console will be spammed with hundreds of rapid setting data lines. (It might take two or three edits, but it always happens consistently in both Firefox and Chrome.
Using react-spreadsheet 0.9.5 but have tried multiple versions ranging back to 0.7.0.
Experiencing the same issue!
Same!
Same issue here!
Here's a temporary workaround which worked for me whilst we wait for a merge.
import _ from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react';
import ReactSpreadsheet from 'react-spreadsheet';
/**
* A component for displaying a spreadsheet.
* @param data
* @param onChange
* @returns {JSX.Element}
* @constructor
*/
export default function Spreadsheet({ data, onChange }) {
const previousData = useRef(data);
const [spreadsheetData, setSpreadsheetData] = useState(data);
/**
* Handle the change of the spreadsheet data.
* @type {(function(*): void)|*}
*/
const handleSpreadsheetChange = useCallback(updatedData => {
// If the data is different to the previous update, set the spreadsheet data.
if (!_.isEqual(spreadsheetData, previousData.current)) {
setSpreadsheetData(updatedData);
// If there's a callback passed, then run it./
if (onChange) {
onChange(updatedData);
}
}
// Update the previous data ref.
previousData.current = updatedData;
}, [spreadsheetData, previousData, onChange]);
useEffect(() => {
console.log('update');
}, [spreadsheetData]);
return <ReactSpreadsheet data={spreadsheetData} onChange={handleSpreadsheetChange} />;
}
@danielgoodwin97 is the solution currently and has fixed the issue I was having.
However, I think that installing the entire lodash package is quite overkill when you only need one function from it.
You can achieve the same functionality by using react-fast-compare
They provide an isEqual function that can be imported in via your usual es6 import:
import isEqual from "react-fast-compare";