11

After upgrading to React 16.0.0 I am now able valid React components that return simple strings without any wrapper elements.

But I would like to do also something like this:

<span title={<FormatterComponent value={someValue} />}>
    Some text text
</span>

I'd like to get a formatted string in title attribute, but I'm getting [object Object] there. Can you help me make this work?

Thanks!

tomexx
  • 2,301
  • 2
  • 20
  • 33
  • 1
    Do you expect `title` to contain the rendered HTML or what? That wouldn't work anyway (see https://jsfiddle.net/gmuvz9xf/), the content of `title` attributes cannot be formatted. See also [Is it possible to format an HTML tooltip (title attribute)?](https://stackoverflow.com/q/484137/218196) – Felix Kling Oct 26 '17 at 00:24
  • 1
    @FelixKling In React 16 you can return strings without wrapper elements. See https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings – tomexx Oct 26 '17 at 00:25
  • 1
    I know. But a) instantiating a react component is still different than calling a function and getting a string back. Evaluating `` does not result in a string. It results in an React element (which is an object). And b) you cannot "style" title attributes. This has nothing to do with React, that's how HTML works. Now, maybe you mean something different by "format". In that case: Whether or not your component returns a string doesn't matter. You cannot use a React component as a value for an HTML attribute. – Felix Kling Oct 26 '17 at 00:29
  • The thing is I'd like to have a formatting functionality bundled in a single place and have there multiple options how to render content. I want to be able to return either formatted result with some wrappers and styling but also as a plain text and use it as ``title`` or other attributes. But if this is not possible then I'll need to break it down somehow and have a separate formatting service just for plain strings. – tomexx Oct 26 '17 at 00:37
  • 4
    If you want all the logic in the same class you can have a static method on `FormatterComponent` that returns a string. E.g. `FormatterComponent.format(someValue)`. – Felix Kling Oct 26 '17 at 00:39
  • I agree with @FelixKling above. Another way to simply create a stand-alone utility function formatting and call that `` – omdel Oct 26 '17 at 00:46

1 Answers1

0

You are getting the [object Object] because the jsx tag, is something different from what you assume it to be.

First, to solve your issue, as long as FormatterComponent is a function component, you could use it as a regular function here.

function FormatterComponent(props) {
  return props.value;
}

export default function App() {
  return (
    <span title={FormatterComponent({ value: "someValue" })}>
      <FormatterComponent value={"someOtherValue"} />
    </span>
  );
}

which will result in:

<span title="someValue">someOtherValue</span>

In fact, as you can see, for the title you have to use the function call FormatterComponent(), while within the span element you can still use the jsx tag <FormatterComponent />.

The reason is, browsers can't utilise jsx. So it has to be transpiled by babel first, which will turn it into this ugly js.

...
function App() {
  return /*#__PURE__*/React.createElement("span", {
    title: FormatterComponent({
      value: "someValue"
    })
  }, /*#__PURE__*/React.createElement(FormatterComponent, {
    value: "someOtherValue"
  }));
}

As you can see, event after the transpilation, for the title the function call remains, which will still result in a string. But the jsx is turned into this:

 React.createElement(FormatterComponent, {
        value: "someOtherValue"
  }));`

The result of which is an object, that is further used by react to built up the html structure.

Keep in mind, the function call for the title, will only work while the FormatterComponent is returning a string. If it returns another jsx, you will have the same issue.

Nice to know: react without jsx.

henk
  • 2,677
  • 2
  • 18
  • 49