React-intl,使用 api 和 Typescript

Posted

技术标签:

【中文标题】React-intl,使用 api 和 Typescript【英文标题】:React-intl, use api with Typescript 【发布时间】:2017-04-08 15:56:15 【问题描述】:

我想使用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 不应该返回一个没有这个道具的组件吗?)

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

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

感谢您的帮助!

【问题讨论】:

【参考方案1】:

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

【讨论】:

对我不起作用...但是将“扩展 React.Component”更改为“扩展 React.PureComponent”可以。 对我来说也很重要...“导出默认值”必须在被导出的类之后! 我又编辑了一遍。确实,你需要将导出行放在文件末尾,你可以扩展“InjectedIntlProps”而不是手动添加 intl props【参考方案2】:

在处理同样的问题时,我发现既不包括 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);

【讨论】:

【参考方案3】:

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

要修复它,我必须明确告诉injectIntl 包装的组件应该有什么道具:

interface NameFormProps 


class NameForm extends React.Component<NameFormProps & InjectedIntlProps> 


export default injectIntl<NameFormProps>(NameForm);

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

class NameForm extends React.Component<InjectedIntlProps> 


export default injectIntl<>(NameForm);

【讨论】:

【参考方案4】:

更新:

在阅读了关于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 不再存在,它被命名为@987654326 @ 代替。

我的示例代码:

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)

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于React-intl,使用 api 和 Typescript的主要内容,如果未能解决你的问题,请参考以下文章

react-intl 实现 React 国际化多语言

使用 react-intl 组件/字符串国际化

使用 React-intl 的 Redux-form 字段级验证和错误翻译

React-Intl 如何从变量切换语言环境和消息

如何将 react-intl 2 与 redux 一起使用?

如何处理 React-Intl 消息的多次使用?