【发布时间】:2021-03-16 19:48:14
【问题描述】:
更改列的hidden 状态后,我无法重新渲染网格。我认为修改 columns 会导致网格重新渲染,因为它是一个绑定属性。
这是一个在codesandbox.io 托管的交互式示例。
index.jsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
App.js
import React from "react";
import SuperTable from "./components/SuperTable";
const data = [
{ id: 1, type: "Developer", name: "Bob", age: 21 },
{ id: 2, type: "Developer", name: "Mary", age: 28 },
{ id: 3, type: "Manager", name: "Steve", age: 42 }
];
const columns = [
{
field: "id",
title: "ID",
searchable: true,
hidden: true
},
{
field: "name",
title: "Name",
searchable: true
},
{
field: "age",
title: "Age",
searchable: true
},
{
field: "type",
title: "Type",
searchable: true
}
];
const App = () => {
return <SuperTable data={data} columns={columns} />;
};
export default App;
SuperTable.jsx
import MaterialTable from "material-table";
import React, { forwardRef } from "react";
import { makeStyles } from "@material-ui/core/styles";
import ArrowDownward from "@material-ui/icons/ArrowDownward";
import ChevronLeft from "@material-ui/icons/ChevronLeft";
import ChevronRight from "@material-ui/icons/ChevronRight";
import ClearIcon from "@material-ui/icons/Clear";
import FirstPage from "@material-ui/icons/FirstPage";
import LastPage from "@material-ui/icons/LastPage";
import Search from "@material-ui/icons/Search";
import ColumnToggler from "./ColumnToggler";
const useStyles = makeStyles((theme) => ({
wrapper: {
display: "flex",
flexDirection: "row"
},
widget: {
display: "flex",
flexDirection: "column",
flex: 0.5
}
}));
const tableIcons = {
ResetSearch: forwardRef((props, ref) => <ClearIcon {...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} />
)),
Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />)
};
const SuperTable = (props) => {
const { data, columns, ...rest } = props;
const classes = useStyles();
const onToggle = (columnField, show) => {
const foundColumn = columns.find((col) => col.field === columnField);
if (foundColumn) {
foundColumn.hidden = show;
}
};
return (
<div className={classes.wrapper}>
<MaterialTable
style={{
position: "unset",
display: "flex",
flexDirection: "column",
flex: 1
}}
title={null}
data={data}
columns={columns}
icons={tableIcons}
pageSize={5}
{...rest}
/>
<div className={classes.widget}>
<ColumnToggler onChange={onToggle} columns={columns} />
</div>
</div>
);
};
SuperTable.propTypes = {
...MaterialTable.propTypes
};
export default SuperTable;
ColumnToggler.jsx
import React from "react";
import { Typography } from "@material-ui/core";
import PropTypes from "prop-types";
import { Container, makeStyles } from "@material-ui/core";
import ColumnToggleSwitch from "./ColumnToggleSwitch";
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 200
}
}));
const ColumnToggler = (props) => {
const { columns, onChange } = props;
const classes = useStyles();
const toggleChecked = (field, show) => {
onChange(field, show);
};
console.log("Updated toggler...");
return (
<Container className={classes.formControl}>
<Typography>Toggle Columns</Typography>
{columns.map((column) => (
<ColumnToggleSwitch column={column} onChange={toggleChecked} />
))}
</Container>
);
};
ColumnToggler.propTypes = {
onChange: PropTypes.func.isRequired
};
export default ColumnToggler;
ColumnToggleSwitch.jsx
import React, { useState } from "react";
import PropTypes from "prop-types";
import { FormControlLabel, FormGroup, Switch } from "@material-ui/core";
const ColumnToggleSwitch = (props) => {
const {
column: { field, hidden, title },
onChange
} = props;
const [checked, setChecked] = useState(hidden == null || !hidden);
const handleChange = (event, newValue) => {
setChecked(newValue);
onChange(event.currentTarget.name, newValue);
};
return (
<FormGroup>
<FormControlLabel
control={
<Switch
key={field}
name={field}
checked={checked}
onChange={handleChange}
color="primary"
inputProps={{ "aria-label": "primary checkbox" }}
size="small"
/>
}
label={title || field}
/>
</FormGroup>
);
};
ColumnToggleSwitch.propTypes = {
column: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired
};
export default ColumnToggleSwitch;
package.json
{
"dependencies": {
"@material-ui/core": "4.11.2",
"@material-ui/icons": "4.11.2",
"material-table": "1.69.2",
"react": "17.0.0",
"react-dom": "17.0.0",
"react-scripts": "3.4.3"
}
}
【问题讨论】:
标签: javascript reactjs data-binding