Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

NumberFormat/DateTimeFormat getters, with support for named formats. #1376

Closed
skoging opened this issue Jul 23, 2019 · 4 comments · Fixed by #1387
Closed

NumberFormat/DateTimeFormat getters, with support for named formats. #1376

skoging opened this issue Jul 23, 2019 · 4 comments · Fixed by #1387

Comments

@skoging
Copy link
Contributor

skoging commented Jul 23, 2019

Is your feature request related to a problem? Please describe.
There is currently no well supported way to use named formats from react-intl, in combination with formatToParts() or resolvedOptions() (or any other methods on the format objects other than format()).

There have been requests for adding these functions before, but it is reasonable that that is out of the scope of this project.

Describe the solution you'd like

const intl = useIntl();
const formatter = intl.getNumberFormatter({ format: "currency" }); // <--

// const parts = formatter.formatToParts(100.12);
// const opts = formatter.resolvedOptions();

Instead, exporting getter functions for creating the NumberFormat/DateTimeFormat objects with support for named formats is sufficient, and would not introduce breaking changes or add too much noise to the API.

Describe alternatives you've considered
While this is possible to achieve now, without any changes to react-intl, it's not pretty. We've gone through a few iterations on this in our app, but our current implementation boils down to replicating the internal functionality of react-intl, to implement these getter functions ourself.

Additional context
A central part of our app is forms with a lot of currency and percent fields, and also some date fields. These are formatted and masked, and should ideally be configured the same way as plain number formatting. It should ideally be as simple as

<NumberInput format="currency_input" value={val} onChange={handleChange} />

or even

function CurrencyInput(props) {
  return <NumberInput format="currency_input" {...props} />;
}

This is not something that is in scope for react-intl itself, and should be relegated to complimentary packages.

With this getter feature in place I'd feel confident enough to open source our formatted input logic, and make it available as complementary packages to react-intl.

@skoging
Copy link
Contributor Author

skoging commented Jul 23, 2019

If this feature is welcome, I'd be open to contributing it myself.

@longlho
Copy link
Member

longlho commented Jul 23, 2019

I think this already exists (intl.getNumberFormat() gives u the instance)

@skoging
Copy link
Contributor Author

skoging commented Jul 23, 2019

If you're thinking of

intl.formatters.getNumberFormat(locale: string, options: Intl.NumberFormatOptions)

then yes, that takes the same arguments as the Intl.NumberFormatter constructor and returns a memoized instance. However, it does not handle react-intl named formats. This is handled in the implementation of the formatter functions themselves

intl.formatNumber(value: number, options: FormatNumberOptions)

The only way I've managed to combine named formats with other formatter methods like formatToParts or resolvedOptions is to reimplement the logic for getting a named format. I also implemented the same logic for filtering props, but that's more of a convenience.

@longlho
Copy link
Member

longlho commented Jul 23, 2019

hmm gotcha. Yeah I'll think about how to maybe extract that out. The imperative APIs do need some enhancement in that aspect.

longlho added a commit that referenced this issue Aug 2, 2019
Also introduces `createIntl` and `RawIntlProvider`
fixes #1386 
fixes #1376 

## Creating intl without using Provider

We've added a new API called `createIntl` that allows you to create an `IntlShape` object without using `Provider`. This allows you to format things outside of React lifecycle while reusing the same `intl` object. For example:

```tsx
import {createIntl, createIntlCache, RawIntlProvider} from 'react-intl'

// This is optional but highly recommended
// since it prevents memory leak
const cache = createIntlCache()

const intl = createIntl({
  locale: 'fr-FR',
  messages: {}
}, cache)

// Call imperatively
intl.formatNumber(20)

// Pass it to IntlProvider
<RawIntlProvider value={intl}>{foo}</RawIntlProvider>
```

This is especially beneficial in SSR where you can reuse the same `intl` object across requests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants