Reactjs 如何在React 0.14中的选项标记内使用FormattedMessage?

Reactjs 如何在React 0.14中的选项标记内使用FormattedMessage?,reactjs,Reactjs,我正在尝试将我的应用程序从React 0.12迁移到React 0.14,并且在使用放置在select标记中的FormattedMessage对象的选项元素时遇到问题 下面是一个示例JSX代码: <select> <option value="value1"><FormattedMessage message={this.getIntlMessage('key1')}/></option> <option value="value2">

我正在尝试将我的应用程序从React 0.12迁移到React 0.14,并且在使用放置在select标记中的FormattedMessage对象的选项元素时遇到问题

下面是一个示例JSX代码:

<select>
<option value="value1"><FormattedMessage message={this.getIntlMessage('key1')}/></option>
<option value="value2"><FormattedMessage message={this.getIntlMessage('key2')}/></option>
</select>

这段代码在React 0.12中运行良好,我看到了已翻译的选项元素

在react 0.14中,我得到了以下错误:

Only strings and numbers are supported as <option> children.
仅支持将字符串和数字作为子项。
我在今年早些时候的React中跟踪了这条消息:


如何解决此问题?我不是唯一一个尝试使用国际化选项元素的人?

这一直是个问题。React<0.14用于以静默方式接受无效的DOM结构,在您的情况下是
元素中的
元素。然后,浏览器将更正DOM结构,并导致React管理的虚拟DOM与真实DOM不同步。在尝试重新呈现现有组件而不是重新装载它们之前,您不会看到错误

react intl
V2.0.0将附带对react 0.14的支持,它允许您使用函数作为子模式来自定义
格式化的*
组件的渲染方式。请参见上的“作为子女抚养人的职能”一段

在您的情况下,您将执行以下操作:


{(消息)=>{message}
{(消息)=>{message}

我认为在当前的稳定版本1.2.1上没有办法实现这一点。

作为@Alexandre Kirszenberg answer更好的替代方案,也可以将
intl
对象注入组件并直接使用
formatMessage
函数

import { injectIntl, intlShape, defineMessages, FormattedMessage } from 'react-intl';

const AddressForm = ({ intl, street, number, postalCode, city, onChange }) => {
  return (
    <form id="paymentAddress">
      // ...
      <fieldset className="form-group">
        <label htmlFor="country"><FormattedMessage { ...messages.country } />:</label>
        <div>
          <select name="country">
            <option value="DE">{intl.formatMessage(messages.de)}</option>
            <option value="UK">{intl.formatMessage(messages.uk)}</option>
            <option value="CH">{intl.formatMessage(messages.ch)}</option>
          </select>
        </div>
      </fieldset>
    </form>
  );
};

AddressForm.propTypes = {
  intl: intlShape.isRequired,
  // ...
}
从'react intl'导入{injectIntl,intlShape,defineMessages,FormattedMessage};
const AddressForm=({intl,street,number,postalCode,city,onChange})=>{
返回(
// ...
:
{intl.formatMessage(messages.de)}
{intl.formatMessage(messages.uk)}
{intl.formatMessage(messages.ch)}
);
};
AddressForm.propTypes={
intl:intlShape.isRequired,
// ...
}

我遇到了同样的问题,并通过injectIntl()解决了它

此函数用于包装组件,并将IntlProvider创建的intl上下文对象作为道具注入包装组件。使用HOC工厂函数可以减少将上下文作为公共API一部分的需要

这意味着您只需使用injectIntl函数包装组件,如下所示:

import React, {Component, PropTypes} from 'react';
import {defineMessages, injectIntl, intlShape} from 'react-intl';

const messages = defineMessages({
    firstoption: {
        id: 'mycomponent.firstoption',
        defaultMessage: 'Coffee',
    },
    secondoption: {
        id: 'mycomponent.secondoption',
        defaultMessage: 'Tea',
    }
});

class MyComponent extends Component {
    render() {
        const {formatMessage} = this.props.intl;

        return (
          <div>
             <select>
                <option value="value1">{formatMessage(messages.firstoption)}</option>
                <option value="value2">{formatMessage(messages.secondoption)}</option>
             </select>
          </div>
        );
    }
}

MyComponent = {
    intl   : intlShape.isRequired
};

export default injectIntl(MyComponent)
import React,{Component,PropTypes}来自'React';
从'react intl'导入{defineMessages,injectIntl,intlShape};
常量消息=定义消息({
第一种选择:{
id:'mycomponent.firstoption',
defaultMessage:“咖啡”,
},
第二种选择:{
id:'mycomponent.secondoption',
defaultMessage:'茶',
}
});
类MyComponent扩展组件{
render(){
const{formatMessage}=this.props.intl;
返回(
{formatMessage(messages.firstoption)}
{formatMessage(messages.secondoption)}
);
}
}
MyComponent={
intl:intlShape.isRequired
};
导出默认injectIntl(MyComponent)

希望这有助于…

使用
injectIntl
包装您想要在其中使用API的组件,这样您就可以使用API,例如
formattedMessage
等等。请参见使用
react intl
v4.0.0您可以执行以下操作:

    <select
      className="content"
      name="type-enquiry"
      defaultValue="Type of Enquiry"
      onChange={handleChange}
      required
     >
      <option name="options" disabled hidden>
                Choose
      </option>
        <FormattedMessage id='contact.enquiry.a' key={'op' + '-' + 'a'}>
           {(message) => <option value='a'>{message}</option>}
        </FormattedMessage>
        <FormattedMessage id='contact.enquiry.b' key={'op' + '-' + 'b'}>
           {(message) => <option value='b'>{message}</option>}
        </FormattedMessage>
        <FormattedMessage id='contact.enquiry.c' key={'op' + '-' + 'c'}>
           {(message) => <option value='c'>{message}</option>}
        </FormattedMessage>
    </select>

选择
{(消息)=>{message}
{(消息)=>{message}
{(消息)=>{message}

工作片段

<FormattedMessage
   key={key}
   id={popoverOptions[key].id}
   defaultMessage={popoverOptions[key].defaultMessage}>
   {(message) => <option value={key}>{message}</option>}
</FormattedMessage>

{Object.keys(popoverOptions).map((键,索引)=>{
返回(
{(消息)=>{message}
)
})}

如果OP不需要进行格式化,他们可以在选项中执行
这个.getIntlMessage('key1')
?有点疏忽,没有公开完整的底层翻译方法。你是对的,在OP的例子中,
this.getIntlMessage('key1')
将返回正确的消息。请注意,V2.0.0API确实公开了上下文上的翻译方法。只要我不使用任何占位符,它似乎就可以工作。。。。我不敢相信没有稳定的方法可以做到这一点?如果我必须在多个组件上使用格式,那又如何呢。我在哪里可以本地注入intl属性,这样当用户调用格式化消息时,他就不必每次都注入intl。因此,当您使用组件时,您将向所需的intl属性传递什么?我假设这是由注入处理的,但是我在使用组件的编辑器中得到一个错误,说缺少必需的属性intl。这只是编辑问题吗?“MyComponent=”应该是“MyComponent.propTypes=”。。。?
"babel-plugin-react-intl": "2.4.0",
<FormattedMessage
   key={key}
   id={popoverOptions[key].id}
   defaultMessage={popoverOptions[key].defaultMessage}>
   {(message) => <option value={key}>{message}</option>}
</FormattedMessage>
"reactstrap": "5.0.0-beta",
import { Input} from "reactstrap";
import {FormattedMessage} from "react-intl";
<Input 
        value={filter.status} 
        onChange={this.onFilterChange} 
        type="select"
        name="select" id="exampleSelect">
        {Object.keys(popoverOptions).map((key, index) => {
            return (
                    <FormattedMessage
                     key={key}
                     id={popoverOptions[key].id}
                     defaultMessage={popoverOptions[key].defaultMessage}>
                          {(message) => <option value={key}>{message}</option>}
                    </FormattedMessage>
                 )
         })}
</Input>