React-intl,在 Typescript 中使用 api

React-intl, use api with Typescript

我想使用 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 道具的类型,因为 IntlShape 似乎没有提供 formatMessage 方法。

我添加了一个?到 intl 道具,因为我一直有一个 Property 'intl' is missing(但 injectIntl 不应该 return 没有这个道具的组件吗?)

现在它可以编译,但是当 运行 我得到一个错误 Cannot read property 'displayName' of undefined。我想这是因为默认导出没有明确的名称)。

我觉得我的方向不对,但找不到任何 typescript/react-intl 项目的例子。

感谢您的帮助!

问题出在打字稿定义的版本上。 当使用 @types/react-intl": "^2.2.0" 时,它就像一个魅力。

(edit) 只需进行少量更改即可使其正常工作:

//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);

已更新:

看了upgrade to 3.x的文档后,我发现它有一个更简单的方法,只需使用useIntl hook:

示例代码:

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)

对于那些现在来到这个话题的人来说 InjectedIntlProps 当前版本的 react-intl 不再支持类型。而是使用 WrappedComponentProps

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