Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - setting up dynamic FormattedMessage - error "Messages must be statically"

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

like image 859
Rob Avatar asked Jan 27 '26 01:01

Rob


1 Answers

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.

like image 190
Clarity Avatar answered Jan 29 '26 16:01

Clarity