React-intl,使用带有Typescript

时间:2016-11-24 11:06:51

标签: typescript react-intl

我想使用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>
    );
}

我使用InjectedIntlProps作为intl prop的类型,因为IntlShape似乎没有提供formatMessage方法。

我添加了?因为我一直有一个&#34; Property&#39; intl&#39;缺少&#34; (但是,如果没有这个道具,我不应该注入一个组件?)

现在它编译,但是在运行时我得到一个错误(&#34;无法读取属性&#39; displayName&#39;未定义&#34;我想因为默认导出没有明确的名称)。

我觉得我没有朝着正确的方向前进,但找不到任何打字稿/反应国际项目的例子。

感谢您的帮助!

5 个答案:

答案 0 :(得分:10)

在处理同样的问题时,我发现,如问题中所提到的那样,既不包括InjectedIntlProps也不包括InjectedIntlProps,也不会像另一个答案中提到的那样从中扩展,它会满足类型检查器。从injectIntl扩展时,对intl的调用已经检查,但是使用JSX中的结果组件需要我提供 interface NameFormProps { // Include all custom properties here. } class NameForm extends React.Component<NameFormProps & InjectedIntlProps, {}> { // Class body. } export default injectIntl(NameForm); 属性。以下策略解决了这个问题:

width

答案 1 :(得分:7)

问题是由于打字稿定义的版本。 当使用@ 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);

答案 2 :(得分:3)

现有的解决方案都不适用于我。而是由于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);

答案 3 :(得分:3)

已更新:

在阅读有关upgrade to 3.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)

答案 4 :(得分:1)

对于现在访问此线程的人来说,当前版本的 InjectedIntlProps 不再支持 react-intl 类型。而是使用 WrappedComponentProps

import { WrappedComponentProps } from 'react-intl';
  
interface IProps extends WrappedComponentProps {
  // other props
}