У меня возникли проблемы с библиотекой react-tabulator
в ReactJS. когда я пытаюсь использовать компонент ReactTabulator
и передать значение реквизита data
(которое мне нужно получить из хранилища Redux), компонент выдает ошибку («MachineID» доступен только для чтения) [Подробнее см. ScreenShot]. Я также попробовал табличный компонент TanStack, и он работает отлично, поэтому я не уверен, что здесь делаю не так!
Библиотеки Редукса:
"react-redux": "^9.1.0"
"redux": "^5.0.1"
"@reduxjs/toolkit": "^2.2.1"
Мой код:
import * as React from "react";
import { useSelector } from "react-redux";
import "react-tabulator/lib/styles.css"; // required styles
import "react-tabulator/lib/css/tabulator.min.css"; // theme
import { ReactTabulator } from "react-tabulator";
import { useEffect, useState } from "react";
const CostSheet = () => {
// TRY ONE
const { basic_costsheet } = useSelector((state) => state.qm.costsheet);
// TRY TWO
const [data, setData] = useState(basic_costsheet);
// TRY THREE
const mod_arr = basic_costsheet.map((e) => e);
// TRY FOUR
const mod_arr_two = [];
basic_costsheet.forEach((element) => {
mod_arr_two.push(element);
});
// TRY FIVE
const cs_data = [
{
McID: 1,
MachineID: "1",
MachineName: "m1",
MaxLength: 1020,
},
{
McID: 2,
MachineID: "2",
MachineName: "m2",
MaxLength: 1050,
},
{
McID: 3,
MachineID: "3",
MachineName: "m3",
MaxLength: 1050,
},
{
McID: 4,
MachineID: "41",
MachineName: "m4",
MaxLength: 1060,
},
];
const columns = [
{ title: "MachineID", field: "MachineID" },
{ title: "MachineName", field: "MachineName" },
{ title: "MaxLength", field: "MaxLength" },
];
const options = {
layout: "fitColumns",
pagination: "local",
paginationSize: 10,
movableColumns: true,
resizableRows: true,
initialSort: [{ column: "MachineID", dir: "asc" }],
};
return (
<div>
<ReactTabulator
columns = {columns}
data = {basic_costsheet} // TRY FIVE works as i pass static data or set data directly in useState.
options = {options}
/>
{/* Every variable/state/redux state gets printed perfectly so the data is loading (IF AVAILALBE). no issues on that front! */}
<pre>{String(JSON.stringify(basic_costsheet))}</pre>
<pre>{String(JSON.stringify(data))}</pre>
<pre>{String(JSON.stringify(mod_arr))}</pre>
<pre>{String(JSON.stringify(mod_arr_two))}</pre>
<pre>{String(JSON.stringify(cs_data))}</pre>
</div>[![][1]][1]
);
};
export default CostSheet;
🤔 А знаете ли вы, что...
React поддерживает создание контекста для передачи данных между компонентами.
Похоже, проблема в том, что ReactTabulator
каким-то образом изменяет объекты массива data
, и это нарушается при использовании значений непосредственно из хранилища, созданного Redux-Toolkit (RTK). Это связано с тем, что RTK использует Immer.js под капотом и обеспечивает, чтобы выбранное состояние было доступно только для чтения. Другими словами, чтобы вы не выстрелили себе в ногу, изменив состояние.
Однако вы можете просто создать новые ссылки на объекты данных, которые не связаны напрямую со значениями вашего Магазина. Мелко скопируйте массив basic_costsheet
и мелко скопируйте каждый элемент массива.
Примеры:
const { basic_costsheet } = useSelector((state) => state.qm.costsheet);
...
<ReactTabulator
columns = {columns}
data = {basic_costsheet.map(item => ({ ...item }))}
options = {options}
/>
const basic_costsheet = useSelector((state) => state.qm.costsheet
.basic_costsheet
.map(item => ({ ...item }))
);
...
<ReactTabulator
columns = {columns}
data = {basic_costsheet}
options = {options}
/>