#javascript #reactjs #typescript #redux
Вопрос:
Я, кажется, не могу понять, что вызывает вышеуказанную проблему, и правильно отлаживаю. Исходя из моего понимания срезов Redux, я могу напрямую изменять состояние в своем редукторе благодаря встроенной функции Immer. Если я жестко закодирую redux JSON в компонент пользовательского интерфейса, то не возникнет никаких проблем, которые заставили бы меня поверить, что это проблема с Redux. Буду признателен за любой совет.
Срез.тс
interface LoadSchedulerState {
gridData: DataRow[] | null,
}
interface DataRow {
id: number,
dis: string,
hour: string
}
const initialState: LoadSchedulerState = {
gridData: null,
}
export const loadSchedulerSlice = createSlice({
name: 'load_scheduler',
initialState,
reducers: {
updateGridData: (state, action: PayloadAction<DataRow>) => {
let newData = [{...action.payload}]
return {...state, gridData:newData}
},
},
});
export const {updateGridData} = loadSchedulerSlice.actions;
export const gridData = (state: { loadScheduler: { gridData: any; }; }) => state.loadScheduler.gridData;
export default loadSchedulerSlice.reducer;
LoadScheduler.ts
import { AgGridColumn, AgGridReact } from "@ag-grid-community/react";
import HeaderGroupComponent from "./HeaderGroupComponent.jsx";
import LoadHeaderComponent from "./LoadHeaderComponent.jsx";
import BtnCellRenderer from './BtnCellRenderer';
import {
AllModules,
ColumnApi,
GridApi,
GridReadyEvent,
} from "@ag-grid-enterprise/all-modules";
import "../../styles/DemoGrid.css";
import { updateGridData, gridData } from "./loadSchedulerSlice";
import { useDispatch, useSelector } from 'react-redux';
const LoadSchedulerGrid = () => {
const [gridApi, setGridApi] = useState<GridApi>();
const [columnApi, setColumnApi] = useState<ColumnApi>();
const [rowData, setRowData] = useState<any>(null);
const gridStateData = useSelector(gridData);
const dispatch = useDispatch();
// PUSH TABLE CHANGES VIA WEBSOCKET TO BACKEND
const handleCellChange = (event: any) => {
}
var init_data = {
id: 0,
dis: "Mon 10/19 8:09 A",
hour: "8 a"
}
const dataSetter = (params: { newValue: any; data: any; }) => {
params.data.dis = params.newValue;
return false;
};
const onGridReady = (params: GridReadyEvent) => {
dispatch(updateGridData(init_data))
setGridApi(params.api);
setColumnApi(params.columnApi);
};
return (
<div className="ag-theme-alpine demo-grid-wrap">
<AgGridReact
onGridReady={(params) => {
onGridReady(params);
}}
immutableData={true}
rowData={gridStateData}
getRowNodeId={node => node.id}
modules={AllModules}
onCellValueChanged={handleCellChange}
defaultColDef={{
resizable: true,
sortable: true,
filter: true,
headerComponentFramework: LoadHeaderComponent,
headerComponentParams: {
menuIcon: "fa-bars",
},
}}
>
<AgGridColumn headerName="#" width={50} checkboxSelection sortable={false} suppressMenu filter={false} pinned></AgGridColumn>
<AgGridColumn headerName="Load Details" headerGroupComponentFramework={HeaderGroupComponent}>
<AgGridColumn field="dis" width={110} headerName="Dispatch" editable cellClass="dispatch" valueSetter={dataSetter} />
<AgGridColumn field="hour" width={50} headerName="Hour" cellClass="hour" />
</AgGridColumn>
</AgGridReact>
</div>
);
};
const rules = {
dc_rules:{
"cell-blue": (params: { value: string }) => params.value === 'ERD',
"cell-beige": (params: {value: string }) => params.value === 'PDC',
"cell-cyan": (params: {value: string }) => params.value === 'CRD'
},
nr_cube_rules:{
"cell-red": (params: {value: number }) => params.value > 10.0
}
}
export default LoadSchedulerGrid;
Ответ №1:
Ag-grid по умолчанию пытается напрямую изменить объект состояния за пределами редуктора. Вы должны использовать настройку Ag-сетки immutableData
.
https://www.ag-grid.com/javascript-data-grid/immutable-data/
У них даже есть статья в блоге об использовании RTK с Ag-сеткой (даже если они используют неизменяемую логику в редукторах — в редукторах RTK это не обязательно, как вы правильно заметили): https://blog.ag-grid.com/adding-removing-rows-columns-ag-grid-with-react-redux-toolkit/
Комментарии:
1. Я добавил неизменяемый тип данных, а также функцию getRowID, но ошибка по-прежнему сохраняется. Я попытался следовать учебнику и все еще застрял. Буду признателен за любую дальнейшую помощь. Я могу успешно загружать данные из хранилища, просто не удается, как только я редактирую ячейку ( даже без вызова обработчика onCellChange).
2. Можете ли вы обновить примеры кода и, возможно, даже предоставить воспроизведение?
3. Примеры кода в вопросе были обновлены.
4. Вам нужно будет написать
valueSetter
метод в вашем столбце, и это нужно сделатьreturn false
в конце, иначе ag-grid все равно попытается написать на объекте.5. Вы не можете изменить объект непосредственно в этом методе набора данных, так как он находится в состоянии восстановления, и вы можете изменить состояние восстановления только путем отправки действия. (Так что вам придется отправить сюда…) Вы уверены, что хотите сохранить его в Redux здесь в первую очередь? В этом случае было бы лучше сохранить его в состоянии локального компонента.