Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[DataGrid] apiGridRef subscribeEvent is undefined #2904

Closed
2 tasks done
wesyao opened this issue Oct 18, 2021 · 34 comments
Closed
2 tasks done

[DataGrid] apiGridRef subscribeEvent is undefined #2904

wesyao opened this issue Oct 18, 2021 · 34 comments
Labels
component: data grid This is the name of the generic UI component, not the React module!

Comments

@wesyao
Copy link

wesyao commented Oct 18, 2021

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version (in v4)

Current behavior 😯

We're currently on @material-ui/x-grid@4.0.0-alpha.37 (we're currently working on the v5 migration) and using the paid xgrid component. @material-ui/core@4.12.3 as well. I'm trying to subscribe to some table events for some additional logic. I've followed the tutorial, even forked my own to test and read the docs many times. It appears to be quite trivial, however I am getting an exception that is being throw with this set code:

  const apiRef = useGridApiRef();
  useEffect(() => {
    apiRef.current.subscribeEvent(GridEvents.columnsChange, (params) => {
      console.log(params);
    });
  }, [apiRef]);
  

an error occurs and crashes react rendering:

  TypeError: apiRef.current.subscribeEvent is not a function

subscribeEvent is undefined and I cannot subscribe to a grid event. This causes an exception to be thrown. I haven't been able to find anyone talking about it on the issues as well as stackoverflow. Looking for some help here!

Thanks in advance!

Expected behavior 🤔

I expect to be able to print out the params.

Steps to reproduce 🕹

Context 🔦

I am trying to use use apiRef.current.subscribeEvent to subscribe to some grid event changes.

Your environment 🌎

`npx @mui/envinfo`
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.
    System:
    OS: macOS 11.6
    CPU: (8) x64 Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
    Memory: 3.92 GB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.11.1 - ~/.nvm/versions/node/v16.11.1/bin/node
    npm: 8.0.0 - ~/.nvm/versions/node/v16.11.1/bin/npm
    Watchman: 2021.09.13.00 - /usr/local/bin/watchman

Order ID 💳 (optional)

idk right now

@wesyao wesyao added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Oct 18, 2021
@flaviendelangle
Copy link
Member

Hi, @wesyao thanks for raising this. Can you please provide the codesabdox reproduction? You can use this template https://codesandbox.io/s/material-ui-issue-next-o7xkt as a starting point.

A reason could be if you do not render the DataGrid during the 1st render.

@flaviendelangle flaviendelangle added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Oct 18, 2021
@TimOwe
Copy link

TimOwe commented Oct 18, 2021

Hi @flaviendelangle , Running into this on my end too, here's a codesandbox:
https://codesandbox.io/s/zen-panka-ex5d6?file=/src/Demo.tsx

@flaviendelangle
Copy link
Member

flaviendelangle commented Oct 18, 2021

@TimOwe the apiRef is currently a pro-only feature and therefore only available for DataGridPro.

If you have a pro-license, here is the fixed code : https://codesandbox.io/s/practical-benz-es6zs?file=/src/Demo.tsx
I passed the apiRef prop to the Grid and changed the installed package.

@TimOwe
Copy link

TimOwe commented Oct 18, 2021

@TimOwe the apiRef is currently a pro-only feature and therefore only available for DataGridPro.

Ah, gotcha. The structure of the docs I'm looking at confused me a bit,
Thanks

@flaviendelangle
Copy link
Member

@TimOwe can you please link me the doc page you are talking about ? I can probably improve the formulation 👍

@TimOwe
Copy link

TimOwe commented Oct 18, 2021

Sure, here
It's using apiRef here but says the same approach can be used with DataGrid.
In hindsight it's obvious but in the moment I hadn't realised!

@flaviendelangle flaviendelangle added component: data grid This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation and removed status: waiting for author Issue with insufficient information labels Oct 18, 2021
@flaviendelangle
Copy link
Member

This demo shows how you can validate a username asynchronously and prevent the user from committing the value while validating. It's using DataGridPro but the same approach can be used with DataGrid.

I agree that this formulation for a code example that uses the apiRef is misleading.

@wesyao
Copy link
Author

wesyao commented Oct 18, 2021

Hi, @wesyao thanks for raising this. Can you please provide the codesabdox reproduction? You can use this template https://codesandbox.io/s/material-ui-issue-next-o7xkt as a starting point.

A reason could be if you do not render the DataGrid during the 1st render.

Hey @flaviendelangle thanks for getting back. I might have been a bit confusing, but the "tutorial" link I posted above was a fork of the demo sandbox and I put in my own package versions to test if it worked.

@flaviendelangle flaviendelangle removed the docs Improvements or additions to the documentation label Oct 18, 2021
@flaviendelangle
Copy link
Member

@wesyao do we agree that this example is not crashing ? https://codesandbox.io/s/material-demo-forked-7qrl7?file=/demo.tsx
Do you have an example with the TypeError: apiRef.current.subscribeEvent is not a function occuring ?

@wesyao
Copy link
Author

wesyao commented Oct 18, 2021

Ah, I get what you mean now, let me rebuild some of it out and I'll get back to you ASAP. Thanks much!

@wesyao
Copy link
Author

wesyao commented Oct 18, 2021

@flaviendelangle, so it might be tough to replicate my component in any meaningful way that isn't different than the forked demo. I'll still continue on it, but was wondering if there were a couple things to look out for or was glanced over on the docs?

  • I'm using relay to fetch data prior to this useEffect, but this is the only useEffect.
  • We have a wrapper component that is rendering XGrid. I tried to move the useEffect block right before render as well. No change.

@flaviendelangle
Copy link
Member

If your XGrid wrapper is doing something like:

const WrappedXGrid = props => {
  const isLoading = useFetchSomeData();

  if (isLoading) {
    return null;
  }

  return <XGrid {...props} />
}

Then you will have the apiRef.current.subscribeEvent is not a function because during the 1st render effect you don't have the Grid yet.

@flaviendelangle
Copy link
Member

I'm closing this issue from lack of feedback

@lowly2005
Copy link

@flaviendelangle I'm getting the same error and I have the premium datagrid license. Using this documentation

@flaviendelangle
Copy link
Member

Hi,

Could you provide a working reproduction, this Codesandbox template might be a good starting point.

@lowly2005
Copy link

lowly2005 commented Sep 13, 2022

@flaviendelangle This is how I'm using the row grouping here
In the code sandbox I don't have any issue but I get this error in my project :

useKeepGroupedColumnsHidden.js:33 Uncaught TypeError: props.apiRef.current.subscribeEvent is not a function
    at useKeepGroupedColumnsHidden.js:33:26
    at invokePassiveEffectCreate (react-dom.development.js:23487:20)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:3945:14)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:16)
    at invokeGuardedCallback (react-dom.development.js:4056:31)
    at flushPassiveEffectsImpl (react-dom.development.js:23574:9)
    at unstable_runWithPriority (scheduler.development.js:646:12)
    at runWithPriority$1 (react-dom.development.js:11276:10)
    at flushPassiveEffects (react-dom.development.js:23447:14)
    at performSyncWorkOnRoot (react-dom.development.js:22269:3)
    "@mui/x-data-grid-premium": "^5.17.2",
    "@mui/x-license-pro": "^5.16.0",

@flaviendelangle
Copy link
Member

Are you passing the apiRef both to useKeepGroupedColumnsHidden and DataGridPremium ?
Without a reproduction of the bug it will be hard for me to help.

@lowly2005
Copy link

@flaviendelangle yes I am

@flaviendelangle
Copy link
Member

Is your DataGridPremium component renderer conditionally ?
In other words, could the useEffect in useKeepGroupedColumnsHidden run before the 1st rendering of the grid ?

@lowly2005
Copy link

@flaviendelangle yes it seems that it's running before the 1st rendering of the grid.

@flaviendelangle
Copy link
Member

You will probably have to create a wrapper with only useKeepGroupedColumnsHidden and useGridApiRef

In most situations, you should not create the apiRef in a component with conditional rendering because it cause lots of issues (maybe we could improve the doc)

@lowly2005
Copy link

Could you share an example of a wrapper with only useKeepGroupedColumnsHidden and useGridApiRef?

@flaviendelangle
Copy link
Member

Here you are

@pythonruss
Copy link

Could the team consider revisiting this? was forced to completely re-write my component just to hide the columns (because of the hook aspects mentioned above).
Not a good upgrade experience for premium -- grouping was why we purchased the library

@sterlingdcs-damian
Copy link

Are you passing the apiRef both to useKeepGroupedColumnsHidden and DataGridPremium ? Without a reproduction of the bug it will be hard for me to help.

I was just bitten by this, and hadn't passed apiRef, I think maybe the error message thrown might be improved to mention needing to pass this prop

@yasin-shaikh
Copy link

yasin-shaikh commented Aug 21, 2024

I have fixed this issue by passing the creating new component for DataGridPremium and pass in my parent component then it fixed
Screenshot 2024-08-21 at 2 41 32 PM
and the initialize state pass inside DataGridPremium

import { Alert, Box, Card, CardContent, Grid, Typography, } from '@mui/material';
import { grey } from '@mui/material/colors'
import { DataGridPremium, GridToolbarColumnsButton, GridToolbarContainer, GridToolbarDensitySelector, gridClasses, GridToolbarFilterButton, useGridApiRef, useKeepGroupedColumnsHidden } from '@mui/x-data-grid-premium';
import Markdown from 'markdown-to-jsx'
import React from 'react'
interface CommonProps {
    data: any, props: any, builder: any, columnGroupingModel: any, rowGroupingModel: any, pinnedRows: any, setRowGroupingModel: any
}
const DataGridComp: React.FC<CommonProps> = ({ data, props, builder, columnGroupingModel, rowGroupingModel, pinnedRows, setRowGroupingModel }) => {
    const apiRef = useGridApiRef();

    const initialState = useKeepGroupedColumnsHidden({
        apiRef,
        initialState: {
            rowGrouping: {
                model: ['question'],
            },
        },
    });
    const CustomToolbar = () => {
        return (
            <GridToolbarContainer>
                <GridToolbarColumnsButton slotProps={{ button: { sx: { color: '#2B7BA7' } } }} />
                <GridToolbarFilterButton slotProps={{ button: { sx: { color: '#2B7BA7' } } }} />
                <GridToolbarDensitySelector
                    slotProps={{ button: { sx: { color: '#2B7BA7' } } }}
                />
                <Box sx={{ flexGrow: 1 }} />

            </GridToolbarContainer>
        );
    }

    return (
        <Grid>
            <Card className="card-decoration">
                <CardContent>
                    <Grid container spacing={2} sx={{ mb: 2 }}>
                        <Grid item xs={12}>
                            <Typography sx={{ fontSize: 16 }}>{data?.name}</Typography>
                            {(data?.dataset || props.dataset) == 'simulated' && (
                                <Alert severity="warning" sx={{ mt: 1 }}>
                                    Simulated data
                                </Alert>
                            )}
                        </Grid>
                    </Grid>
                    <Box sx={{ height: '100% !important' }}>
                        <DataGridPremium
                            apiRef={apiRef}
                            initialState={initialState}
                            rows={builder.rows}
                            columns={builder.getColumns()}
                            columnGroupingModel={columnGroupingModel}
                            checkboxSelection={false}
                            rowHeight={35}
                            columnHeaderHeight={35}
                            hideFooter
                            pinnedRows={pinnedRows}
                            slots={{
                                toolbar: CustomToolbar,
                            }}
                            resizeThrottleMs={0}
                            sx={{
                                [`& .${gridClasses.columnHeader}`]: {
                                    bgcolor: grey[200], borderInlineEnd: `1px solid #ddd`, borderBlockEnd: `1px solid #ddd`
                                },
                                [`& .${gridClasses.columnHeaderTitle}`]: {
                                    color: 'black', fontSize: 14, fontWeight: 900, textTransform: 'capitalize', bgcolor: grey[200]
                                },
                                [`& .${gridClasses['row--borderBottom']}`]: { bgcolor: ` ${grey[200]} !important`, },
                                [`& .${gridClasses.cell}`]: {
                                    borderInlineEnd: `1px solid #ddd`
                                },
                                [`& .${gridClasses.toolbarContainer}`]: {
                                    borderBlockEnd: `1px solid #ddd`,
                                },
                                [`& .${gridClasses.cellEmpty}`]: {
                                    bgcolor: 'white ', border: `none  !important`
                                },
                                [`& .${gridClasses.virtualScroller}`]: {
                                    overflowY: 'auto !important',
                                    maxHeight: 'calc(100vh - 10px) !important',

                                },
                                [`& {.super-app-theme--auto-generated-row-question/Brand Rating}`]: { bgcolor: `${grey[200]} !important` }


                            }}
                            defaultGroupingExpansionDepth={-1}
                            rowGroupingModel={rowGroupingModel}
                            onRowGroupingModelChange={(model) => { setRowGroupingModel(model) }}
                        />
                    </Box>
                    {data?.insights && (
                        <Markdown className="markdown">{data?.insights}</Markdown>
                    )}
                </CardContent>
            </Card>
        </Grid>)
}

export default DataGridComp

@igortas
Copy link

igortas commented Sep 26, 2024

I need help wth this too, I have wrapper on top of mui x grid, it have conditional statement that returns null, and above is the useKeepGroupedColumnsHidden hook. It's so bad that conditional breaks the shared wrapper for mui x grid.

@flaviendelangle
Copy link
Member

@michelengelen I'm adding you to the loop 🙏

@michelengelen
Copy link
Member

This seems very clear to me:
Screenshot 2024-09-30 at 15 43 27
Maybe discoverability is not high enough for this. We use the apiRef very frequently in the examples and have near 0 explanations regarding this specific behavior other than here.

@alelthomas @samuelsycamore tagging you as well as this is clearly docs related.

@mapache-salvaje
Copy link
Contributor

mapache-salvaje commented Sep 30, 2024

It does seem like the relevant doc is getting lost in the Advanced section. I don't love that header name—who decides what's truly "advanced" anyway? (If this is something that I need to rely on then I would probably think of it as a "basic" or "fundamental" feature, but those are also pretty arbitrary designations.) Is there a better place for the three "advanced" docs to live?

@flaviendelangle
Copy link
Member

The three pages under "Advanced" are about behavioral customization. How to plug into the grid system to add some custom behaviors (by calling API methods imperatively, by listening to events or by interacting with the grid's state)

@mapache-salvaje
Copy link
Contributor

In that case, would it make sense to rename "Advanced" to something like "Behavior" or "Custom Behavior" as a first step towards making it easier to find?

@flaviendelangle
Copy link
Member

I would be in favor of going in this direction indeed, not sure what the exact wording should be

@mapache-salvaje
Copy link
Contributor

@flaviendelangle I'll open a PR for that and we can get more feedback on the naming there 🤝

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
component: data grid This is the name of the generic UI component, not the React module!
Projects
None yet
Development

No branches or pull requests

10 participants