React-intl APIのformatMessage関数を使用して、プレースホルダーとしてメッセージを挿入したいのですが、この関数にアクセスする正しい方法がわかりません。
これが私が持っているものの簡略版です:
//index.tsx
<IntlProvider locale={`fr-FR`} messages={messages_fr}>
<NameForm/>
</IntlProvider>,
//nameForm.tsx
interface NameFormProps {
intl?: InjectedIntlProps,
}
export default injectIntl(NameForm);
class NameForm extends React.Component<NameFormProps, {}> {
render() {
let namePlaceholder = this.props.intl.formatMessage(
{id: "NAME_PLACEHOLDER",
defaultMessage: "name"
});
return (
<form>
<input placeholder={namePlaceholder} type="text"/>
</form>
);
}
IntlShapeはformatMessageメソッドを提供していないようであるため、intlpropのタイプとしてInjectedIntlPropsを使用しました。
?を追加しました「プロパティ 'intl'がありません」(ただし、injectIntlはこのプロパティなしでコンポーネントを返すことになっていないのですか?)
これでコンパイルされますが、実行時にエラーが発生します(「デフォルトのエクスポートには明示的な名前がないため、「未定義のプロパティ 'displayName'を読み取れません」と思います)。
正しい方向に進んでいないように感じますが、TypeScript/react-intlプロジェクトの例が見つかりません。
ご協力いただきありがとうございます !
この問題は、TypeScript定義のバージョンが原因でした。 @ types/react-intl ":" ^ 2.2.0 "を使用すると、チャームのように機能します。
(編集)それを機能させるために必要ないくつかの変更:
//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);
同じ問題を処理しているときに、質問で述べたようにメンバーとしてInjectedIntlProps
を含めたり、別の回答で述べたようにそこから拡張したりしても、タイプチェッカーが満たされないことがわかりました。 InjectedIntlProps
から拡張する場合、injectIntl
の呼び出しがチェックされましたが、JSXで結果のコンポーネントを使用すると、intl
プロパティを提供することが期待されました。ただし、次の戦略でこれを解決しました。
interface NameFormProps {
// Include all custom properties here.
}
class NameForm extends React.Component<NameFormProps & InjectedIntlProps, {}> {
// Class body.
}
export default injectIntl(NameForm);
既存のソリューションはどちらも私にはうまくいきませんでした。代わりに、injectIntl
がプロパティにInjectedIntlProps
を含めるように推測したことが原因でした。
これを修正するには、ラップされたコンポーネントに必要な小道具をinjectIntl
に明示的に指示する必要がありました。
interface NameFormProps {
}
class NameForm extends React.Component<NameFormProps & InjectedIntlProps> {
}
export default injectIntl<NameFormProps>(NameForm);
小道具がない場合は、少し変更する必要があります。
class NameForm extends React.Component<InjectedIntlProps> {
}
export default injectIntl<{}>(NameForm);
更新しました:
.xへのアップグレード に関するドキュメントを読んだ後、useIntl
フックを使用するだけの簡単な方法があることがわかりました。
サンプルコード:
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
古い:
React-intlの新しいバージョン(3.12.0)では、@types/react-intl
はもう必要ありません。react-intlには独自の型定義があり、InjectedIntlProps
はもう存在せず、名前が付けられています。代わりにWrappedComponentProps
。
私のサンプルコード:
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)