React-intl, use api with Typescript
Updated:
After reading the docs about upgrade to 3.x, I found it has a simpler way, just use useIntl
hook:
Sample code:
import { FormattedMessage, useIntl } from 'react-intl'
type Props = {
placeholder: string,
}
function MyComponent({ placeholder }: Props) {
const intl = useIntl()
return (
<input placeholder={intl.formateMessage({id: placeholder})} type="text"/>
)
}
export default MyComponent
Old:
In the react-intl new version (3.12.0), we don't need @types/react-intl
anymore, react-intl has its own type definition, and InjectedIntlProps
doesn't exist anymore, it is named WrappedComponentProps
instead.
My sample code:
import { FormattedMessage, injectIntl, WrappedComponentProps } from 'react-intl'
type Props = {
placeholder: string,
} & WrappedComponentProps
function MyComponent({ placeholder, intl }: Props) {
return (
<input placeholder={intl.formateMessage({id: placeholder})} type="text"/>
)
}
export default injectIntl(MyComponent)
The problem was due to the version of the typescript definition. When using @types/react-intl": "^2.2.0", it works like a charm.
(edit) Few changes needed to make it work :
//index.tsx
<IntlProvider locale={`fr-FR`} messages={messages_fr}>
<NameForm/>
</IntlProvider>,
//nameForm.tsx
interface NameFormProps extends InjectedIntlProps {
placeholder: string,
}
class NameForm extends React.Component<NameFormProps, {}> {
render() {
let namePlaceholder = this.props.intl.formatMessage({
id: this.props.placeholder,
defaultMessage: "name"
});
return (
<form>
<input placeholder={namePlaceholder} type="text"/>
</form>
);
}
export default injectIntl(NameForm);
While working with the same problem, I found that neither including InjectedIntlProps
as a member, as mentioned in the question, nor extending from it, as mentioned in another answer, satisfies the type checker. When extending from InjectedIntlProps
, the call to injectIntl
checked, but using the resulting component in JSX expected me to provide an intl
property. The following strategy resolved this though:
interface NameFormProps {
// Include all custom properties here.
}
class NameForm extends React.Component<NameFormProps & InjectedIntlProps, {}> {
// Class body.
}
export default injectIntl(NameForm);
Neither of the existing solutions worked for me. Instead it was due to injectIntl
inferring the properties to include InjectedIntlProps
.
To fix it, I had to explicitly tell injectIntl
what props the wrapped component should have:
interface NameFormProps {
}
class NameForm extends React.Component<NameFormProps & InjectedIntlProps> {
}
export default injectIntl<NameFormProps>(NameForm);
If there are no props, it needs to be changed slightly:
class NameForm extends React.Component<InjectedIntlProps> {
}
export default injectIntl<{}>(NameForm);