2015-10-30 9 views
8

Sto provando a migrare la mia applicazione da React 0.12 a React 0.14 e sto riscontrando problemi con gli elementi opzione che utilizzano gli oggetti FormattedMessage react-intl inseriti all'interno di tag selezionati.Come utilizzare FormattedMessage all'interno di un tag di opzione in React 0.14?

Ecco un codice di esempio JSX:

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

Questo codice funziona bene in Reagire 0,12 e vedo i miei elementi opzionali tradotti.

In reagire 0.14, ho ottenuto questo errore:

Only strings and numbers are supported as <option> children. 

ho tracciato il messaggio a questo changeset a reagire che è accaduto all'inizio di quest'anno:

https://github.com/facebook/react/pull/3847/files

Come posso risolvere il problema ? Non posso essere l'unico a cercare di utilizzare elementi di opzione internazionalizzati?

risposta

12

Questo è sempre stato un problema. React < 0.14 utilizzato per accettare in silenzio la struttura DOM non valida, nel tuo caso gli elementi <span> all'interno degli elementi <option>. Il browser correggerebbe quindi la struttura DOM e farebbe sì che il DOM virtuale gestito da React non fosse sincronizzato con la cosa reale. Non vedresti errori finché non proverai a ri-renderizzare i componenti esistenti invece di limitarli a montarli di nuovo.

react-intl V2.0.0, che sarà disponibile con supporto per Reagire 0.14, consente di utilizzare il modello di funzione-As-sitter per personalizzare il modo in cui i componenti Formatted* rendering. Vedere il paragrafo "Supporto di funzione come figlio" su this issue.

Nel tuo caso, si farebbe:

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

Non credo ci sia un modo per raggiungere questo obiettivo sulla versione stabile attuale, 1.2.1.

+0

Se l'OP non ha bisogno di fare la formattazione potrebbe semplicemente fare 'this.getIntlMessage ('key1')' all'interno dell'opzione? Un po 'di svista per non esporre l'intero metodo di traduzione sottostante imo –

+1

Hai ragione, nel caso dell'OP, 'this.getIntlMessage (' key1 ')' restituirebbe il messaggio corretto. Si noti che la V2.0.0 API espone i metodi di traduzione sul contesto. –

+3

Sembra che funzionerà a patto che non utilizzi alcun segnaposto .... Non posso credere che non ci sia un modo stabile per farlo? –

2

Come un po 'meglio alternativa @Alexandre Kirszenberg risposta, è anche possibile iniettare intl oggetto nel componente Utilizzando formatMessage funzione direttamente,

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, 
    // ... 
} 
10

Ho avuto lo stesso problema e risolto tramite l'injectIntl ​​().

This function is used to wrap a component and will inject the intl context object created by the IntlProvider as a prop on the wrapped component. Using the HOC factory function alleviates the need for context to be a part of the public API.

Questo significa che tutto quello che dovete fare è avvolgere il componente con la funzione injectIntl, come quella:

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) 

Speranza che aiuta ...

+0

come se dovessi usare la formattazione su più componenti. Dove posso iniettare localmente l'intl prop in modo che quando l'utente chiama i messaggi di formattazione, non deve iniettare l'intl ogni volta – user1234

+1

Quindi, quando si usa il componente, cosa si passa all'attributo intl richiesto? Presumo che questo fosse gestito dall'iniezione, ma ricevo un errore nel mio editor in cui viene usato il componente dicendo che manca un attributo obbligatorio intl. È solo un editore? –

0

Usa injectIntl per avvolgere il componente desidera utilizzare l'API all'interno, quindi è possibile utilizzare l'API, ad esempio formattedMessage e così via. Vedi react-intl/wiki/API

Problemi correlati