KevinVandy/material-react-table

Localization props doesn't work with proxy object

AliceCengal opened this issue · 4 comments

material-react-table version

2.0.3

react & react-dom versions

18.2.0

Describe the bug and the steps to reproduce it

I am using next-translate, and have prepared an MRT locales map in my local language. But MRT expects the map to be an object, whereas next-translate provide a function t, so I thought I would make a Proxy to connect these two together.

However, the table seems to be still showing the default text labels, and my proxy get method was never called according to the console log.

I expect the localization props to work with Proxy object that simulates a locale object using next-translate t function.

Minimal, Reproducible Example - (Optional, but Recommended)

import useTranslation from 'next-translate/useTranslation'
import dynamic from 'next/dynamic'
import { ReactElement, useCallback, useMemo } from 'react'

import type { MRT_ColumnDef, MRT_Localization } from 'material-react-table'
const DatagridTable = dynamic(
  () => import('material-react-table').then((res) => res.MaterialReactTable),
  { ssr: false },
)

export function Datagrid() {
  const { t, lang } = useTranslation('datagrid')
  const columns = []
  const initialState = {}

  const i18nProxy = useMemo(
    () =>
      new Proxy({}, {
        get(target, prop) {
          console.log('Datagrid i18n proxy called', prop)
          return t(prop)
        },
      }),
    [lang],
  )

  return (
      <DatagridTable
        columns={columns}
        data={[]}
        localization={i18nProxy }
      />
  )
}

Screenshots or Videos (Optional)

No response

Do you intend to try to help solve this bug with your own PR?

None

Terms

  • I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

As long as the object that you pass to localization is the correct shape, it should work.

There is some code under the hood like this:

localization = useMemo(
  () => ({
    ...MRT_Localization_EN,
    ...localization,
  }),
  [localization],
);

Just make sure that the reference to localization is updated in any values inside of it have changed.

Right, object merging like that wouldn't work with a Proxy object, since the proxy doesn't have any real field (not the "right shape"). You could maintain the current behaviour while adding compatibility with next-translate by doing the merge like this:

localization = useMemo(
  () =>
    Object.fromEntries(
      Object.keys(MRT_Localization_EN).map((k) => [
        k,
        localization?.[k] ?? MRT_Localization_EN[k],
      ]),
    ),
  [localization],
)

why can't you do the above in your own code before passing it to MRT?

I can, and I am currently doing this. Just wondering if you are open to adding compatibility with function-based translation instead of dictionary object. If not, feel free to close this issue, let this issue be documentation for how to use next-translate with MRT.