我正在尝试将我的应用程序从React 0.12迁移到React 0.14,并且使用放置在select标签内的react-intl 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中正常工作,我看到了我翻译的选项元素。
在反应0.14中,我收到了这个错误:
Only strings and numbers are supported as <option> children.
我在今年早些时候发生的React中追踪了这个变化集:
https://github.com/facebook/react/pull/3847/files
如何解决此问题?我不能成为唯一一个尝试使用国际化选项元素的人吗?
答案 0 :(得分:14)
这一直是个问题。反应&lt; 0.14用于静默接受无效的DOM结构,在var data = [{
data: [
[1, 5],
[2, 3]
],
highlightColor: "#00FF00"
}, {
data: [
[1, 2],
[2, 8]
],
highlightColor: "#FF0000",
}];
元素内的<span>
元素中。然后,浏览器将更正DOM结构,并使React管理的虚拟DOM与真实事物不同步。在尝试重新渲染现有组件而不是仅重新安装它们之前,您不会看到错误。
<option>
V2.0.0,它将支持React 0.14,允许您使用Function-As-Child模式来自定义react-intl
组件的呈现方式。请参阅this issue上的“功能 - 儿童支持”段落。
在你的情况下,你会这样做:
Formatted*
我认为目前的稳定版本1.2.1没有办法实现这一目标。
答案 1 :(得分:12)
我有同样的问题,并通过injectIntl()解决了它。
此函数用于包装组件,并将IntlProvider创建的intl上下文对象作为包装组件的prop进行注入。使用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)
希望有帮助...
答案 2 :(得分:2)
作为@Alexandre Kirszenberg回答的一个更好的替代方案,它也可以将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,
// ...
}
答案 3 :(得分:1)
使用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>
答案 4 :(得分:0)
使用injectIntl
包装您要在其中使用API的组件,以便您可以使用API,例如formattedMessage
等。见react-intl/wiki/API
答案 5 :(得分:0)
"react-intl": "2.4.0",
"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>