Material-ui: Expose RadioGroupContext via useRadioGroup Hook

Created on 19 Dec 2019  路  10Comments  路  Source: mui-org/material-ui

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Summary 馃挕

Expose RadioGroupContext via useRadioGroup Hook (cf. useFormControl).

Examples 馃寛

https://codesandbox.io/s/material-demo-9w4yc

Motivation 馃敠

I'd like the ability to easily work out whether a wrapped Radio is checked, so I can apply custom styling to a checked label, for example (see demo above). In MUI v3, this was possible because RadioGroup would use cloneElement and pass checked prop to children. With the new context implementation (https://github.com/mui-org/material-ui/pull/15069), I now need to hook into the context but because it's not part of public API, I'd need to use a Babel transform to import the correct module (CJS vs ESM) in my library output:

  • @material-ui/core/RadioGroup/RadioGroupContext
  • @material-ui/core/esm/RadioGroup/RadioGroupContext

@oliviertassinari has pointed out that we're currently exposing FormControlContext via a custom useFormControl Hook, so we could probably do the same in this instance? I'm happy to raise a PR for this.

Prior art: https://github.com/mui-org/material-ui/issues/11865

Radio docs good to take

All 10 comments

That looks fine to me. I can't remember a situation where exposing the context as read-only has locked us into a "bad" API.

While this specific customization is doable without using RadioGroupContext I think we can allow this.

While this specific customization is doable without using RadioGroupContext I think we can allow this.

Oh, how would you do it instead?

exposing the context as read-only

Do you mean excluding values such as update functions from what's returned by useRadioGroup?

While this specific customization is doable without using RadioGroupContext I think we can allow this.

Oh, how would you do it instead?

Manually do the checked test and pass it to MyFormControlLabel: https://codesandbox.io/s/material-demo-6dbb3. It's not pretty but does the job. Likely based on personal experience whether you prefer maintaining repetition or internals of third party libraries.

Is there a way to hook into the RadioGroupContext or any other way to get the currently selected value from RadioGroup's value? I'm also after creating a wrapper around Radio, and not using FormControlLabel.

By importing the RadioGroupContext, and trying to use it I'm getting undefined as in the consumer. I could go with creating a custom FormControlLabel, but I don't really want nor need to create a generic one which would work for other form elements - I'm only after creating custom Radios. Or would it be better for my custom Radio to already contain FormControlLabel?

I'm reopening as I believe we miss:

  • A section in the documentation.
  • ~To export useRadioGroup in the barrel index (js and ts).~

I am seeing a weird situation. When I am importing the RadioGroup and useRadioGroup like this

import RadioGroup from '@material-ui/core/RadioGroup';
import useRadioGroup from '@material-ui/core/RadioGroup/useRadioGroup';

I notice that the context is being created twice. This is because @material-ui/core/RadioGroup points to the module in the esm folder and @material-ui/core/RadioGroup/useRadioGroup points to the module in the root (cjs) target.

However, if I do

import RadioGroup, { useRadioGroup }  from '@material-ui/core/RadioGroup';

Then both modules refer to the same esm module

Basically, because they refer to modules in different places, the context created on import is also different. I cannot repro this on codesandbox, but I can repro this locally. I assume codesandbox uses UMD so this problem would not be prevalent there. Got a small hole in my knowledge as I don't know exactly why it choses to go for the cjs in the first example.

@oliviertassinari

I am seeing a weird situation. When I am importing the RadioGroup and useRadioGroup like this

import RadioGroup from '@material-ui/core/RadioGroup';
import useRadioGroup from '@material-ui/core/RadioGroup/useRadioGroup';

@joonarahko that works as expected, you're not supposed to import beyond the 2nd level. The second way you showed is the correct way: https://material-ui.com/guides/minimizing-bundle-size/#option-1

You may find this ESLint plugin useful (currently not published, so just paste it into your project): https://github.com/mui-org/material-ui/blob/27471b4/packages/eslint-plugin-material-ui/src/rules/restricted-path-imports.js

Ok :) Makes sense. Thanks @NMinhNguyen

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TimoRuetten picture TimoRuetten  路  3Comments

revskill10 picture revskill10  路  3Comments

sys13 picture sys13  路  3Comments

ericraffin picture ericraffin  路  3Comments

pola88 picture pola88  路  3Comments