KevinVandy / material-react-table

A fully featured Material UI V5 implementation of TanStack React Table V8, written from the ground up in TypeScript
https://material-react-table.com
MIT License
1.47k stars 420 forks source link

Localization props doesn't work with proxy object #992

Open AliceCengal opened 7 months ago

AliceCengal commented 7 months ago

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

KevinVandy commented 7 months ago

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.

AliceCengal commented 7 months ago

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],
)
KevinVandy commented 7 months ago

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

AliceCengal commented 6 months ago

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.