Mui Datagrid not populating, data is there - reactjs

I have a few Mui datagrids through my app. I recently switched over to using RTK Query for the api and was able to get all the grids functioning and displaying fine. I honestly do not know what changed (since it took place after I was done mucking with the grid components and was adjusting the auth/login to RTK) but 3 of the 4 are displaying an empty grid with no errors. I can console the data, and even the corner of the grids shows the total number of entries, which reflects the changes if I add an item to the array that should be displayed by the grid. I already had the container components set to display: flex and set autoHeight and autoWidth on the grids. I've tried adjusting the containers, even putting height to 5000, with no change. As I mentioned, I have 1 that still displays correctly, and even copying the display props for that grid to the others had no effect.
import React from 'react';
import PropTypes from 'prop-types';
import { DataGrid, GridActionsCellItem } from '#mui/x-data-grid';
import { Link } from 'react-router-dom';
import { useGetVisitsByUserIdQuery } from '../../redux/apiSlice';
import { CircularProgress, Box } from '#mui/material';
const UserVisits = ({ user }) => {
const userId = user._id
const {
data,
isLoading,
isSuccess
} = useGetVisitsByUserIdQuery(userId);
console.log(data)
const columns =
[
{
field: 'client',
headerName: 'Client',
width: 150,
renderCell: (params) => {
return (
<Link to={`/ClientChart/${params?.value?._id}`}>{params?.value?.fullName}</Link>
)}
},
{
field: 'visitStart',
headerName: 'Start Time',
type: 'date',
width: 200,
valueFormatter: (params) => {
const date = new Date(params.value);
let options = {
year: "numeric",
month: "numeric",
day: "numeric"
};
return date.toLocaleTimeString("en-US", options);
}
},
{
field: 'visitEnd',
headerName: 'End Time',
type: 'date',
width: 200,
valueFormatter: (params) => {
const date = new Date(params.value);
let options = {
year: "numeric",
month: "numeric",
day: "numeric"
};
return date.toLocaleTimeString("en-US", options);
}
},
{field: 'location', headerName: 'Location', width: 150},
];
let content
if (isLoading) {
content = <CircularProgress />
} else if (isSuccess) {
content =
<div style={{ display: 'flex', height: '100%'}}>
<Box sx={{ flexGrow: 1 }}>
{ data &&
<DataGrid
autoHeight
autoWidth
getRowId={(row) => row.id}
rows={data}
columns={columns}
rowsPerPageOptions={[20, 50, 100]}
autoPageSize
//sx={{ height: '100%', width: '100%' }}
/>}
</Box>
</div>
}
return (
<div>
<h1>Visits</h1>
<div>
{content}
</div>
</div>
)
}
If I push new data to the grid, the number of entries in the bottom right corner adjusts, and the console shows the correct array of data, as well as Redux DevTools showing the data in state. Even manually adjusting the height of the div/Box containing the grid, the grid itself never changes in height.
Again they had been working perfectly, and I'm at a total loss as to what would have affected them. Any help is greatly appreciated.
Thanks

So the issue was resolved by removing 'autoPageSize' from the Datagrid props. Playing with it, it seems that autoHeight and autoPageSize cause the grid to break when in place together.
Could not find any specific references online to this being an issue, but I was able to recreate the issue on this codesandbox I found: https://codesandbox.io/s/datagrid-v5-0-1-autoheight-autopagesize-9dy64?file=/src/App.tsx
If you add in autoPageSize to the datagrid props, the grid goes empty.

Related

Fluent-UI's dropdown and combobox both not working

I have a React app with Fluent-UI 8 set up using npm install #fluentui/react according to the documents from Microsoft.
When I try their combobox or dropdown components, the dropdown list doesn't appear when clicked on it. I use their examples from the docs, which compiles without errors. But none of their examples work out of the box, and no other information is provided.
The problem is that the dropdown list does not appear when clicked on. Not in Edge, not in Firefox. When I check the elements on the page, I do not see the html elements with the list items, although I can cycle through them with the arrow keys. The list appears from the side when the window is tablet format, and setting ResponsiveMode did nothing. Whith a normal screen however, nothing is displaying, and no onchange events are fired.
This is my code for the dropdown:
import { IStackTokens, ResponsiveMode, Stack } from '#fluentui/react';
import { Dropdown, DropdownMenuItemType, IDropdownOption, IDropdownStyles } from '#fluentui/react/lib/Dropdown';
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
const DropdownControlledMultiExampleOptions = [
{ key: 'fruitsHeader', text: 'Spooler status', itemType: DropdownMenuItemType.Header },
{ key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' },
{ key: 'grape', text: 'Grape' },
{ key: 'broccoli', text: 'Broccoli' },
{ key: 'carrot', text: 'Carrot' },
{ key: 'lettuce', text: 'Lettuce' },
];
export const DropdownList: React.FunctionComponent = () => {
const stackTokens: IStackTokens = { childrenGap: 20 };
return (
<Stack tokens={stackTokens}>
<Dropdown
placeholder="Select an option"
label="Disabled responsive"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
responsiveMode={ResponsiveMode.unknown}
/>
<Dropdown
placeholder="Select an option"
label="Responsive with panel"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
/>
</Stack>
);
};
Which I load in my app.tsx
function App() {
return (
<div className="App">
<DropdownList/>
</div>
);
}
Does anyone have an idea how I can get this to work? Or what is causing this?
EDIT and possible solution: It seems that removing the <React.Strict> tags in index.tsx does the job. Don't know why, but then the Fluid-UI controls work fine.

Rendering an action menu in Ant Table on Row hover

I'm using Ant table to display some data. So far so good except the requirement that I need to display an action menu when a particular row hovered over. Here's the mock of what I'm trying to achieve:
Ant table's onRow callback will allow me to get the record that's being hovered over and onRowClassName allows me to pass a class name so I can dynamically apply css on the row hovered over. But I'm stuck on rendering an element at the end of the row like you see in the screenshot.
I'm a bit stumbled on how to go about doing this. Closest thing I came across is this context menu implementation: https://codesandbox.io/s/rm23kroqyo
Appreciate any input.
One way to do this is to add a column for the actions and add a className for it.
export const columns = [
{ title: `Name`, dataIndex: `name` },
{ title: `Age`, dataIndex: `age` },
{ title: `Address`, dataIndex: `address` },
{
title: "",
dataIndex: "actions",
render: (actions) =>
actions &&
actions.map((action) => (
<a className="action" href>
{action}
</a>
)),
className: "actions"
}
];
add the actions on the data
const dataWithActions = data.map((item) =>
item.key === "2" ? { ...item, actions: ["Like", "Share"] } : item
);
Then set it's position absolute so it does not take up space
.actions {
position: absolute;
}
.ant-table-row {
position: relative;
}
And finally position it when the row is hovered
.ant-table-row:hover .actions {
display: block;
height: 54px;
right: 0;
}
Here's the updated codesandbox:
https://codesandbox.io/s/custom-context-menu-table-antd-forked-b6y5c

ReactJS - How can I make this option conditional?

I am working with the FlatPickr Date/Time module trying to implement the monthSelect plugin on only those fields that need it. How can I make the plugin option "monthSelectPlugin" line of code conditional based on a prop that I pass in?
(see comments in Flatpickrdatetime.jsx)
I get the following error with the code below. Also, I'm sure there is a better way to make one line of code conditional, and I am here for it, just not sure how.
Error:
Error: Flatpickrdatetime(...): Nothing was returned from render.
This usually means a return statement is missing. Or, to render nothing, return null.
Arrival / Departure page:
import React from 'react';
import { Grid, Typography, FormControl} from '#material-ui/core';
import Flatpickrdatetime from './FormFields/Flatpickrdatetime';
<Grid container item spacing={3}>
<Grid item xs={12} md={6}>
<InputLabel shrink htmlFor="bootstrap-input">Arrival Date</InputLabel>
<Flatpickrdatetime type="monthSelect" />
</Grid>
<Grid item xs={12} md={6}>
<InputLabel shrink htmlFor="bootstrap-input">Depart Date</InputLabel>
<Flatpickrdatetime />
</Grid>
</Grid>
Flatpickrdatetime.jsx
/* https://flatpickr.js.org/examples/ */
import React from 'react';
import { fade, makeStyles } from '#material-ui/core/styles';
import "flatpickr/dist/themes/light.css";
import monthSelectPlugin from "flatpickr/dist/plugins/monthSelect/index.js";
import "flatpickr/dist/plugins/monthSelect/style.css";
import "flatpickr/dist/themes/light.css";
import Flatpickr from "react-flatpickr";
export default function Flatpickrdatetime(props) {
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
margin: {
marginTop: theme.spacing(3),
width:'100%'
},
flatpickr:{
marginBottom:'0.25em',
borderRadius: 4,
}
}));
const classes = useStyles();
{(() => {
if (props.type === 'monthSelect'){
return (
<Flatpickr
options={{
format: "m/d/Y",
altFormat: "m/d/Y",
altInput: true,
allowInput: true,
// if props.type equals monthSelect
plugins: [new monthSelectPlugin({shorthand: false, dateFormat: "Y-m-d", altFormat: "M Y"})]
}}
className={classes.flatpickr} />
);
}else if(props.type != 'monthSelect'){
return (
<Flatpickr
options={{
format: "m/d/Y",
altFormat: "m/d/Y",
altInput: true,
allowInput: true,
// no plugin if props.type does not equal monthSelect
}}
className={classes.flatpickr} />
);
}else{
return null;
}
})()}
}
Your IFFE here {(() => { seems to be the problem. Why do you use it? Just remove it and leave the conditional statement and you should be fine.
your IFFE does return a value, but it is wrapped in a block statement and you miss your return Component. if you had it like below would work, but it's not neat:
return (() => {return something })()
First, I would recommend to define your styles outside of the component. Otherwise each rerender makeStyles is called unnecessary.
Second, you could abstract your options object build logic outside the render part, and avoid all that code duplication. You could useMemo to memorize its value. It will keep the same options unless type changes (you set as dependency).
one more thing, based on your logic null is never hit. It's a not reachable point, it will always render the first or second condition since if one is true the other is false.
after this you could have your component as:
import React, { useMemo } from 'react';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
margin: {
marginTop: theme.spacing(3),
width:'100%'
},
flatpickr:{
marginBottom:'0.25em',
borderRadius: 4,
}
}));
export default function Flatpickrdatetime({ type }) {
const classes = useStyles();
const options = useMemo(() => {
const flatpickOps = {
format: "m/d/Y",
altFormat: "m/d/Y",
altInput: true,
allowInput: true,
}
if (type === 'monthSelect') {
flatpickOps.plugins = [new monthSelectPlugin({shorthand: false, dateFormat: "Y-m-d", altFormat: "M Y"})]
}
return flatpickOps
}, [type])
return <Flatpickr options={options} className={classes.flatpickr} />
}

React DataTable fails to change the font-size

I work on a React app and there is a component using DataTable (reference is here).
The default font-size looks too small so I want to change to make it look bigger.
I try to set the style to the table as the code below but it doesn't work.
Here is my code:
import React from 'react';
import ReactDOM from 'react-dom';
import DataTable from 'react-data-table-component';
export default class MyTable2 extends React.Component {
constructor(props) {
super(props);
const data = [];
for (var i = 0; i < 200; i++) {
data.push({ id: i, title: 'Conan the Barbarian' + i, summary: 'Orphaned boy Conan is enslaved after his village is destroyed...', year: '1982', expanderDisabled: true, image: 'http://conan.image.png' })
}
this.state = {
rs: data
}
}
render() {
const columns = [
{
name: 'Title',
selector: 'title',
sortable: true,
},
{
name: 'Year',
selector: 'year',
sortable: true
},
];
const handleChange = (state) => {
console.log('Selected Rows: ', state.selectedRows);
};
let styleobj = { "font-size": "25px" } //try to set the font-size here
return (
<DataTable
className="dataTables_wrapper"
title="Arnold Movies"
columns={columns}
data={this.state.rs}
selectableRows // add for checkbox selection
onTableUpdate={handleChange}
pagination
style={styleobj}
/>
)
}
}
Is there anyone here can suggest me a solution?
Thank you in advanced.
Can you try this
// Override the row font size
const myNewTheme= {
rows: {
fontSize: '25px'
}
}
<DataTable
className="dataTables_wrapper"
title="Arnold Movies"
columns={columns}
data={this.state.rs}
selectableRows // add for checkbox selection
onTableUpdate={handleChange}
pagination
customTheme={myNewTheme}
/>
Theme reference
Source file
If you want to change an individual cell font size, you can do this
const columns = [
{
name: 'Title',
selector: 'title',
sortable: true,
cell: row => <div style={{fontSize: 25}}>{row.title}</div>
}]
Hi #humanbean answer is correct, you can fix the inline stile or, if you want, you also can set the style directly in your app.css
Based on your custom classname (.dataTables_wrapper) I think that this css should work.
.dataTables_wrapper .rdt_TableCell{
font-size:25px;
}
this is the className used by react-data-table-component
rdt_Table
rdt_TableRow
rdt_TableCol
rdt_TableCol_Sortable
rdt_TableCell
rdt_TableHeader
rdt_TableFooter
rdt_TableHead
rdt_TableHeadRow
rdt_TableBody
rdt_ExpanderRow

Render a component oclick of a row in react-table (https://github.com/react-tools/react-table)

I want to render a component when a row is clicked in a react-table. I know i can use a subcomponent to achieve this but that doesn't allow click on the entire row. I want the subcomponent to render when the user clicks anywhere on that row. From their github page i understand that i want to edit getTdProps but am not really able to achieve it. Also the subcomponent is form and on the save of that form i want to update that row to reflect the changes made by the user and close the form. Any help is appreciated.
import React, {Component} from 'react';
import AdomainRow from './AdomainRow'
import ReactTable from "react-table"
import AdomainForm from './AdomainForm'
import 'react-table/react-table.css'
export default class AdomianTable extends Component {
render() {
const data = [{
adomain: "Reebok1.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
},
{
adomain: "Reebok2.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
},
{
adomain: "Reebok3.com",
name: "Reebok",
iabCategories: ["IAB1", "IAB2", "IAB5"],
status: "PENDING",
rejectionType: "Offensive Content",
rejectionComment: "The content is offensive",
isGeneric: false,
modifiedBy: "Sourav.Prem"
}];
//FOR REACT TABLE TO WORK
const columns = [{
Header : 'Adomian',
accessor : 'adomain'
}, {
Header : 'Name',
accessor : 'name'
}, {
Header : 'IABCategories',
accessor : 'iabCategories',
Cell : row => <div>{row.value.join(", ")}</div>
}, {
Header : 'Status',
accessor : 'status'
}];
return (
<div>
<ReactTable
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: (e, handleOriginal) => {
<AdomainForm row={rowInfo} ></AdomainForm>
console.log('A Td Element was clicked!')
console.log('it produced this event:', e)
console.log('It was in this column:', column)
console.log('It was in this row:', rowInfo)
console.log('It was in this table instance:', instance)
// IMPORTANT! React-Table uses onClick internally to trigger
// events like expanding SubComponents and pivots.
// By default a custom 'onClick' handler will override this functionality.
// If you want to fire the original onClick handler, call the
// 'handleOriginal' function.
if (handleOriginal) {
handleOriginal()
}
}
}
}}
data={data.adomains}
columns={columns}
defaultPageSize={10}
className="footable table table-stripped toggle-arrow-tiny tablet breakpoint footable-loaded"
SubComponent = { row =>{
return (
<AdomainForm row={row} ></AdomainForm>
);
}}
/>
</div>
);
}
}
}
I ran into the same issue where I wanted the entire row to be a clickable expander as React Table calls it. What I did was simply change the dimensions of the expander to match the entire row and set a z-index ahead of the row. A caveat of this approach is that any clickable elements you have on the row itself will now be covered by a full width button. My case had display only elements in the row so this approach worked.
.rt-expandable {
position: absolute;
width: 100%;
max-width: none;
height: 63px;
z-index: 1;
}
To remove the expander icon you can simply do this:
.rt-expander:after {
display: none;
}
I found it was better to add a classname to the react table:
<AdvancedExpandReactTable
columns={[
{
Header: InventoryHeadings.PRODUCT_NAME,
accessor: 'productName',
},
]}
className="-striped -highlight available-inventory" // custom classname added here
SubComponent={({ row, nestingPath, toggleRowSubComponent }) => (
<div className={classes.tableInner}>
{/* sub component goes here... */}
</div>
)}
/>
Then modify the styles so that the columns line up
.available-inventory .-header,
.available-inventory .-filters {
margin-left: -40px;
}
And then modify these styles as Sven suggested:
.rt-tbody .rt-expandable {
cursor: pointer;
position: absolute;
width: 100% !important;
max-width: none !important;
}
.rt-expander:after{
display: none;
}

Resources