1

I'm trying to replace a string with a React Component but it's not working. It's returning [object Object].

I've tried to use renderToString and renderToStaticMarkup from react-dom/server to render the component, but no success.

import React from 'react';

const MyComponent = ({ children }) => <strong>{children}</strong>;

function App() {
  const content = 'Hi @user'.replace('user', <MyComponent>user</MyComponent>);

  return <div className="App" dangerouslySetInnerHTML={{ __html: content }} />;
}

export default App;

Expected result: Hi @<strong>user</strong>

Actual result: Hi @[object Object]

0

2 Answers 2

1

I am using a custom function for this use case (inspired this answer):

function replaceWith(string, replaceThis, replacement){
    return string.split(replaceThis)
                    .map(item => <>{item}</>)
                    .reduce((acc, x) => acc === null ? [x] : [acc, replacement, x], null)
}

Example (with span instead of component):

<h1>
    {replaceWith('Hi @user', '@user', <span>ABC</span>)}
</h1>
Sign up to request clarification or add additional context in comments.

Comments

0

To render components, they need to return those components as part of your rendering. This is typically done with jsx tags, which get transformed into calls to React.createElement, which in turn creates objects that instruct react what to do.

But with string.replace, you're only going to produce a string, not react elements, so react has nothing to work with other than that string. And as for dangerouslySetInnerHtml, that will only work if you have actual dom content you want to insert, not react components (plus, it's dangerous).

Most of the time when you're rendering components of an unknown quantity this is done by having an array of data, which you then map to the components. For example:

function App() {
  const greetings = ['Hi @', 'Aloha @'];
  const content = greetings.map(greeting => (
    <React.Fragment>
      {greeting}
      <MyComponent>user</MyComponent>
    </React.Fragment>
  ));

  return <div>{content}</div>;
}

Taking in a string and trying to interrogate that string is rather unusual, but if that's what you need to do, then you'll probably want to do something like this:

function App() {
  const str = 'Hi @userAloha @user';
  const greetings = str.split('user');
  greetings.pop() // remove an empty string from the end of the array
  const content = greetings.map(greeting => (
    <React.Fragment>
      {greeting}
      <MyComponent>user</MyComponent>
    </React.Fragment>
  ));

  return <div>{content}</div>
}

Note that this is basically identical to my first code, except there's an extra step to turn the string input into an array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.