React-intl,使用带有Typescript的api

Ema*_*rco 8 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>
    );
}
Run Code Online (Sandbox Code Playgroud)

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

我添加了?到了intl prop,因为我一直有"Property'intl'缺失"(但是不是injectIntl​​应该返回没有这个prop的组件吗?)

现在它编译,但在运行时我得到一个错误("无法读取未定义的属性'displayName'"我猜因为默认导出没有明确的名称).

我觉得我没有朝着正确的方向前进,但找不到任何打字稿/ react-intl项目的例子.

谢谢你的帮助 !

小智 13

在处理同样的问题时,我发现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);
Run Code Online (Sandbox Code Playgroud)


Ema*_*rco 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);
Run Code Online (Sandbox Code Playgroud)


Rya*_*all 6

现有的解决方案都不适合我。相反,这是由于injectIntl推断要包含的属性InjectedIntlProps

为了解决这个问题,我必须明确地告诉injectIntl被包裹的组件应该有哪些道具:

interface NameFormProps {
}

class NameForm extends React.Component<NameFormProps & InjectedIntlProps> {
}

export default injectIntl<NameFormProps>(NameForm);
Run Code Online (Sandbox Code Playgroud)

如果没有props,需要稍微改动一下:

class NameForm extends React.Component<InjectedIntlProps> {
}

export default injectIntl<{}>(NameForm);
Run Code Online (Sandbox Code Playgroud)


Spa*_*Bao 6

更新:

阅读关于升级到 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
Run Code Online (Sandbox Code Playgroud)

老的:

在 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)
Run Code Online (Sandbox Code Playgroud)