React JS: как разобрать JSX в строке? - PullRequest
0 голосов
/ 09 мая 2020

У меня есть компонент Пример , который принимает string в качестве опоры и стили , обернув его в контейнер , содержащий CSS классов.

Это то, что Пример выглядит так:

interface Props {
  text: string;
}

const Example: React.FC<Props> = ({ text, }) => (
  <span className="class-a class-b class-c">
    {text}
  </span>
);

Я использую Пример в Компонент Info выглядит следующим образом:

const Info: React.FC = () => (
  <div className="class-x class-y class-z">
    <p>
      I am a simple statement
      <Example text=" but I need some styling" />
      !!!!
    </p>
  </div>
);

Теперь этот компонент Info используется в компоненте Parent следующим образом:

const Parent: React.FC = () => (
  <Info />
);

Задача: Мне нужно сделать этот Информация компонент для повторного использования следующим образом:

const myJSON = {
  val1: "I am a simple statement <Example text=" but I need some styling" 
        />!!!!",
  val2: "Another statement <Example text=" but I need some styling" 
        />!!!!",
}
const Parent: React.FC = () => (
  <Info data={myJSON.va1l} />
  <Info data={myJSON.va2l} />

Теперь, что происходит, это React не может разобрать Пример как компонент в опоре, а отображает в браузере следующим образом:

I am a simple statement <Example text=" but I need some styling" />!!!!
Some other statement <Example text=" with this styling" />!!!!
Another again <Example text=" another styling" />!!!!

Есть ли способ или библиотека, чтобы React анализировал его как компонент?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 09 мая 2020

Это именно то, для чего нужна опора children. При размещении элементов в JSX-компонентах, например:

const Parent: React.FC = () => (
    <Info>
        I am a simple statement
        <Example text=' but I need some styling' />
        !!!!
    </Info>
);

React автоматически отправляет контент в свойство children, которое можно использовать в вашем компоненте:

const Info: React.FC = ({ children }) => (
    <div className='class-x class-y class-z'>
        <p>{children}</p>
    </div>
);
0 голосов
/ 09 мая 2020

Вы можете использовать метод ReactDomServer.renderToString(). Он преобразует компоненты React в строку. Вы можете найти документацию здесь .


Реализация не идеальна, но она отображает содержимое самого внутреннего дочернего элемента.

Родительский компонент

export default function App() {
  let content = ReactDOMServer.renderToString(
    <Example text="but I need some styling" />
  );

  content += " This is extra string";

  return <Info content={JSON.stringify(content)} />;
}

Здесь вы можете преобразовать компонент React в строку и объединить любую строку, которую захотите. Если вы получили компонент уже внутри строки, я предлагаю вам использовать Regex для извлечения компонента.

Дочерний компонент

const Info = ({ content }) => {
  return <Example text={content} />;
};

Как только у вас есть компонент stringified, вы можете передать его как prop.

Самый внутренний ребенок

const Example = ({ text }) => {
  return (
    <span
      className="class-a class-b class-c"
      dangerouslySetInnerHTML={{ __html: text }}
    />
  );
};

В этом компоненте вы можете использовать метод dangerouslySetInnerHTML для установки HTML с помощью кода. Ознакомьтесь с документацией здесь


Как уже говорилось, это действительно не очень хороший подход и сделает вас уязвимым для атак cross-site scripting (XXS). Я предлагаю вам изменить ответ JSON, который вы получаете, если у вас есть контроль над серверной частью.

0 голосов
/ 09 мая 2020

Вы можете изменить свой подход к использованию children props

const Parent: React.FC = () => (
  <Info>I am a simple statement <Example text=" but I need some styling" />!!!!"</Info>

   <Info>"Some other statement <Example text=" with this styling" />!!!!"</Info>
   <Info>"Another again <Example text=" another styling" />!!!!" </Info>
);

const Example: React.FC<Props> = ({ children }) => (
    <span className="class-a class-b class-c">
       {children}
    </span>
);

const Info: React.FC = () => (
  <div className="class-x class-y class-z">
    <p>
      I am a simple statement
      <Example>{children}</Example>
      !!!!
    </p>
  </div>
);
...