I am working on a react application - and when a user inputs a text field - I want a button on the same row - to change from 'generate' to 'save'
<FormattedMessage
id='generate'
defaultMessage='Generate'
/>
but I want something like this
<FormattedMessage
id='generate'
defaultMessage={valueName ? 'Save' : 'Generate'}
/>
or something
<FormattedMessage
id='generate'
defaultMessage={valueName.length > 0 ? 'Save' : 'Generate'}
/>
but when I implement something like this I get the following error
"[React Intl] Messages must be statically evaluate-able for extraction."
https://github.com/formatjs/react-intl/blob/master/docs/Components.md#formattedmessage
You can't do that since the messages have to be defined statically. You need to define both messages and then select one based on your condition:
const generateMsg = (
<FormattedMessage id="generate" defaultMessage={"Generate"} />
);
const saveMsg = <FormattedMessage id="save" defaultMessage={"Save"} />;
const msg = valueName ? saveMsg : generateMsg;
I personally prefer using a small util that abstracts this cumbersome syntax:
// Message.js
import React from "react";
import { injectIntl } from "react-intl";
const Msg = injectIntl(({ id, intl }) => intl.formatMessage({ id }));
const msg = ({ id }) => <Msg id={id} />;
export default msg;
Usage:
import { defineMessages } from "react-intl";
import msg from './Message';
const messages = defineMessages({
save: {
id: "save",
defaultMessage: "Save"
},
generate: {
id: "generate",
defaultMessage: "Generate"
}
})
//...
<p>{msg(valueName ? messages.save : messages.generate)}</p>
Source.
Note that msg can only be used inside React components as it returns a component itself. This means it cannot be used in places that expect a string, like native input'splaceholder, but the same applies to` as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With