3

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

Rob
  • 153
  • 1
  • 12

1 Answers1

4

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.

Clarity
  • 10,730
  • 2
  • 25
  • 35
  • I may need to implement this as a conditional html fragment -- {valueName ? : } – Rob Sep 04 '19 at 12:31
  • I'll accept the answer - although its a bit more complicated - as its surrounded in a button with different actions – Rob Sep 04 '19 at 16:26