Пожалуйста, проверьте эту песочницу, чтобы увидеть проблему:
https://codesandbox.io/s/server-generated-mt-ooc3e
Я стремлюсь иметь файл json, который может включить или отключить функцию в указанной ячейке c. Проблема здесь в том, что столбцы содержат обработчики, которые генерируются только один раз при первом использовании. И, таким образом, функция обработчика запускается только один раз при первом рендеринге, для ее решения я вставил состояние, которое изменяется при щелчке, как зависимость для useEffect, что означает, что он генерирует новые обработчики. Проблема в том, что это слишком медленно. Я думал о разделении на useEffect для столбцов и useEffect для данных, но это кажется плохим решением.
import React, { useState, useEffect, useCallback } from "react";
import MaterialTable from "material-table";
import styled from "styled-components";
// ALL ICONS IMPORT AND REF //
import { forwardRef } from "react";
import AddBox from "@material-ui/icons/AddBox";
import ArrowDownward from "@material-ui/icons/ArrowDownward";
import Check from "@material-ui/icons/Check";
import ChevronLeft from "@material-ui/icons/ChevronLeft";
import ChevronRight from "@material-ui/icons/ChevronRight";
import Clear from "@material-ui/icons/Clear";
import DeleteOutline from "@material-ui/icons/DeleteOutline";
import Edit from "@material-ui/icons/Edit";
import FilterList from "@material-ui/icons/FilterList";
import FirstPage from "@material-ui/icons/FirstPage";
import LastPage from "@material-ui/icons/LastPage";
import Remove from "@material-ui/icons/Remove";
import SaveAlt from "@material-ui/icons/SaveAlt";
import Search from "@material-ui/icons/Search";
import ViewColumn from "@material-ui/icons/ViewColumn";
const tableIcons = {
Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
DetailPanel: forwardRef((props, ref) => (
<ChevronRight {...props} ref={ref} />
)),
Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
PreviousPage: forwardRef((props, ref) => (
<ChevronLeft {...props} ref={ref} />
)),
ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />),
ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
};
// ----------------------------- //
export default function PositioningActionsColumn() {
const [stateColumns, setStateColumns] = useState([]);
const [stateData, setStateData] = useState([]);
const [isOpen, setIsOpen] = useState(true);
useEffect(() => {
fetchTable();
}, [isOpen]);
const fetcher = async urlName => {
const urls = {
columnsUrl: "https://api.myjson.com/bins/128vkm",
dataUrl: "https://api.myjson.com/bins/1adefq"
};
const fetchedData = await fetch(urls[urlName]);
const jsonData = await fetchedData.json();
return jsonData;
};
const fetchTable = async () => {
const jsonColumns = await fetcher("columnsUrl");
const jsonData = await fetcher("dataUrl");
columnsGenerator(jsonColumns);
setStateData(jsonData);
};
const columnsGenerator = jsonColumns => {
const dropDown = <DropDown isOpen={isOpen} />;
const newColumns = jsonColumns.map(columnHeader => {
const title = (
<>
<ObjTitle onClick={handleClick}>{columnHeader.title}</ObjTitle>
{columnHeader.includeDropDown && dropDown}
</>
);
const newHeader = { ...columnHeader, title };
return newHeader;
});
setStateColumns(newColumns);
};
// const handleClick = () => {
// setIsOpen(!isOpen);
// };
const handleClick = useCallback(() => setIsOpen(current => !current), []);
return (
<>
<MaterialTable
title="Editable Preview"
icons={tableIcons}
columns={stateColumns}
data={stateData}
options={{ draggable: false, selection: true }}
/>
<Changing isOpen={isOpen} />
</>
);
}
const ObjTitle = styled.div``;
const DropDown = styled.div`
width: 60px;
height: 60px;
background: steelblue;
display: ${({ isOpen }) => (isOpen ? "block" : "none")};
`;
const Changing = styled.div`
height: 100px;
width: 100px;
background: ${({ isOpen }) => (isOpen ? "black" : "red")};
`;