Используйте Babel Transform внутри кода React

Я пытаюсь преобразовать строку в допустимый код JSX, а затем внедрить ее в свой компонент React.

const babel = require('babel-core')
let result = eval(babel.transform('<p className="greeting">Hello</p>').code)

Но меня сбивает стена ошибок, потому что я пытаюсь использовать Babel в браузере:

ERROR in ./~/babel-core/lib/api/node.js
Module not found: Error: Can't resolve 'fs' in '/Users/ben/Desktop/Work/code/ru-coding-challege/node_modules/babel-core/lib/api'
 @ ./~/babel-core/lib/api/node.js 72:10-23
 @ ./~/babel-core/index.js
 @ ./src/js/containers/app-container.js
 @ ./src/js/index.js
 @ multi (webpack)-dev-server/client?http://localhost:3000 ./src/js/index.js

...more similar errors

Да, я знаю, что создание кода из строки и его внедрение не одобряются, но D3 создает элементы динамически (т.е. вы не можете написать их декларативно). Например: оси, значения и количество тиков которых изменяются в зависимости от данных. Я успешно изменил оси D3 на JSX с помощью htmltojsx, но это возвращает String, Мне нужно повернуть это String в действительные компоненты JSX, которые я могу вставить в свой код.

РЕДАКТИРОВАТЬ: Как Майкл Лайонс заявляет ниже, я мог бы просто использовать dangerouslySetInnerHTML, но я пытаюсь избежать этой опции, если все остальное не работает. Попытка максимально придерживаться парадигмы Реакта.

Вот как будет выглядеть метод рендеринга моего компонента:

<svg width='100%' height='600'>
  <g transform='translate(50, 50)'>
    <path d='...' className='path-0'></path>
  </g>
  {/* Insert JSX elements here. e.g. axes below */}
  {axes}
</svg>

А вот мой webpack.config.js

const CopyWebpackPlugin = require('copy-webpack-plugin')
const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: './src/js/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].bundle.js',
  },
  devServer: {
    inline: true,
    contentBase: path.join(__dirname, 'dist'),
    port: 3000
  },
  plugins: [
    new CopyWebpackPlugin([
      { from: 'src/html/index.html' }
    ]),
    new webpack.DefinePlugin({
      IN_BROWSER: true,
    }),
  ],
  module: {
    loaders: [
      {
        test: /\.scss$/,
        exclude: /(node_modules)/,
        loader: 'style-loader!css-loader!sass-loader'
      },
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
}

1 ответ

Вместо перевода HTML-кода в JSX, а затем рендеринга с помощью babel в коде на клиенте, вы можете рендерить этот html напрямую через компонент React.

Реализация элемента DOM в Facebook имеет встроенную функциональность для этого варианта использования, и вы правы, на него обычно не обращают внимания по соображениям безопасности, поскольку он открывает уязвимости для межсайтовых скриптов.

Facebook даже пометил его как "опасно SetInnerHTML", чтобы напомнить разработчикам, что это опасно.

Поэтому, если у вас есть HTML в строковом формате, вы можете отобразить его в JSX таким образом:

getMarkup() {
  return { __html: '<p class="greeting">Hello</p>' }
}
render() {
  return <div dangerouslySetInnerHTML={this.getMarkup()} />;
}

Это прямо из документации по элементам React DOM здесь: Docs

Этот метод также должен позволить вам обойти необходимость преобразования вывода d3 в JSX

Изменить: вступительное предложение

Другие вопросы по тегам