admin管理员组

文章数量:1355535

I want to introduce a multilingual system. I have a function ponent that returns a translation of a specific element based on selected language (from Context API).

Everything works well until I put the translated element into the form (option value, placeholder, etc.) - then it appears as an [object object].

That's where 2 questions are born:

  1. Is it possible to return this ponent as a something like string, which HTML forms would accept?

  2. Is it possible to apply context consumer to pure JS function, so it does not return a React ponent, but a primitive value?

Translation ponent:

const Translation = ({ element }) => {
  let translation;

  return (
    <LanguageConsumer>
      {({ language }) => {
        switch (language) {
          case "pl":
            translation = plTranslation;
            break;

          case "en":
            translation = enTranslation;
            break;

          default:
            translation = enTranslation;
        }

        return translation[element];
      }}
    </LanguageConsumer>
  );
};

Example:

<option value="en">
  <Translation element="globalLanguageEnglish" />
</option>

Thanks in advance for your help.

I want to introduce a multilingual system. I have a function ponent that returns a translation of a specific element based on selected language (from Context API).

Everything works well until I put the translated element into the form (option value, placeholder, etc.) - then it appears as an [object object].

That's where 2 questions are born:

  1. Is it possible to return this ponent as a something like string, which HTML forms would accept?

  2. Is it possible to apply context consumer to pure JS function, so it does not return a React ponent, but a primitive value?

Translation ponent:

const Translation = ({ element }) => {
  let translation;

  return (
    <LanguageConsumer>
      {({ language }) => {
        switch (language) {
          case "pl":
            translation = plTranslation;
            break;

          case "en":
            translation = enTranslation;
            break;

          default:
            translation = enTranslation;
        }

        return translation[element];
      }}
    </LanguageConsumer>
  );
};

Example:

<option value="en">
  <Translation element="globalLanguageEnglish" />
</option>

Thanks in advance for your help.

Share Improve this question edited Jun 8, 2019 at 7:18 Yilmaz 49.9k18 gold badges217 silver badges270 bronze badges asked Jun 6, 2019 at 21:37 ŁukaszŁukasz 1331 gold badge1 silver badge5 bronze badges 14
  • 2 Can you share some code? React can render a string object correctly. You are most likely trying to render the context object or something else. – Arash Motamedi Commented Jun 6, 2019 at 21:39
  • Hard to help without code / context. However from what you're describing it sounds like you want to dynamically render a ponent based off its name. const ComponentToRender = 'MyComponent'; and using it would be like <ComponentToRender />. So if you have conditional elements to render you can pass just the ponents string name and then render it – John Ruddell Commented Jun 6, 2019 at 21:42
  • Sorry guys, I added some code. I guess the problem is that I am returning whole consumer, not only string element from translation object. – Łukasz Commented Jun 6, 2019 at 21:52
  • Or not. It always gives [object object] in form. Even if you do sth like const Value = () => "value" and pass it to input placeholder like <input type="text" placeholder={<Value />}. :-( – Łukasz Commented Jun 6, 2019 at 22:07
  • In that case you would just call Value as a function instead of rendering it as a ponent: <input type="text" placeholder={Value()} /> – Brian Hadaway Commented Jun 6, 2019 at 22:30
 |  Show 9 more ments

3 Answers 3

Reset to default 0

I can confirm it doesn't work - <option> html element content can be "Text, possibly with escaped characters (like &eacute;)."

React ponent can return only string, it's perfectly valid (and works as OP stated) ... but this use case is not supported.

Using ponents to just return a string is not a good choice. It can be ineffective when you need many translated strings in one ponent. React has to manage it as ponents, control props, render, make reconcilation etc. Many, following ponents (siblings) of the same type (only different props) should be key-ed.

Smarter solution: In this case pass an array of options (keys) as prop and use one ponent to render all translated <option> elements in a loop (return using fragment), f.e. like this:

// get some translation fn f.e. from context
return (
  <>
    {props.items.map( item => <option key="{item}" value="{item}">{translate(item)}</option> )}
  </>
)

Look how it's done at ready i18n solutions like i18next described here - pass function 't' and use it to access your translations.

I had a similar need where I had to support translated strings and wanted to return a "string" from a react ponent. I wanted to be able use the ponent with a typical function call and in the render section. Here is what I ended up doing.

This is the react ponent which returns the "string" value. Side note: I'm using redux to store a dictionary of strings but you can use something else.

import { useSelector } from 'react-redux';

export function StringValue({ stringId }) {
  const myStrings = useSelector((state) => state.strings);

  // Note: do your own error handling as required
  return myStrings[stringId];
}

Here is an example of how to use the ponent with a typical function call and as a ponent in render:

import { StringValue} from 'StringValue';
...

export function MyComponent(){
    ...

    return (
        <>
            {console.log('StringValue ', StringValue({ sId: 'myStringKey' }))}

            <StringValue sId="myStringKey" />
    ...

How about the approach to separate the translation logic from the rendering logic. Instead of returning a ponent that contains the translation, you can create a translation function or custom hook that returns the translated string.

Using a Translation Function or Custom Hook For example, you could create a custom hook that reads the context and returns a function for fetching translation strings:

import React, { useContext } from 'react';
import { LanguageContext } from './LanguageProvider';

const useTranslation = () => {
  const { language } = useContext(LanguageContext);
  const translations = language === 'pl' ? plTranslation : enTranslation;
  return (element) => translations[element];
};

export default useTranslation;

Then in your ponent you can do:

const MyComponent = () => {
  const t = useTranslation();

  return (
    <select>
      <option value="en">{t('globalLanguageEnglish')}</option>
      {/* other options */}
    </select>
  );
};

This way, you’re directly obtaining a string from your translation system rather than trying to render a ponent into a string.

本文标签: javascriptIs there a way to return React Component as string instead of objectStack Overflow