Не удалось выполнить 'removeChild' в 'Node' с FontAwesome в React

Я получаю следующую ошибку, когда я пытаюсь использовать значок Spinner FontAwesome (с className='fa-spin') в React:

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
at removeChild (http://localhost:5000/public/bundle.js:19553:22)
at unmountHostComponents (http://localhost:5000/public/bundle.js:13683:11)
at commitDeletion (http://localhost:5000/public/bundle.js:13727:5)
at commitAllHostEffects (http://localhost:5000/public/bundle.js:14419:13)
at HTMLUnknownElement.callCallback (http://localhost:5000/public/bundle.js:5035:14)
at Object.invokeGuardedCallbackDev (http://localhost:5000/public/bundle.js:5074:16)
at invokeGuardedCallback (http://localhost:5000/public/bundle.js:4931:27)
at commitRoot (http://localhost:5000/public/bundle.js:14508:9)
at performWorkOnRoot (http://localhost:5000/public/bundle.js:15510:42)
at performWork (http://localhost:5000/public/bundle.js:15460:7)

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

return (
  <div>
    {this.state.loading === true ? <i className="fa-spin fas fa-sync"></i> : (
      this.state.recipes.length === 0 ? (
        <div className='text-center'>
          <h2>There doesn't seem to be anything here...</h2><br />
          <h2 style={buttonStyle}>Get started by </h2><button style={buttonStyle} className='btn btn-md btn-success' onClick={(e) => this.props.setView(e, 'browserecipes')}>browsing existing recipes</button><h2 style={buttonStyle}> or </h2><button style={buttonStyle} className='btn btn-success btn-md' onClick={(e) => this.props.setView(e, 'addrecipe')}>adding a recipe.</button>
        </div>
      ) : (
      <div>
          <h1 className='text-center title'>My Recipe Cloud</h1>
          <RecipeContainer
            recipes={this.state.recipes}
            user={this.state.user}
            tags={this.props.tags}
            setView={this.props.setView}
            changeUser={this.changeUser}
          />
        </div>
      )
    )}
  </div>

)

Ответ 1

Я думаю, я понял, почему это происходит. Похоже, это связано с тем, что FontAwesome 5 заменяет теги <i> тегами <svg>. Я считаю, что это несовместимо с тем, как React обрабатывает удаление элементов из DOM. см.: https://fontawesome.com/how-to-use/svg-with-js#with-jquery

Обходной путь, который я использую, указан в нижней части этой документации, которая должна включать:

<script>
  FontAwesomeConfig = { autoReplaceSvg: 'nest' }
</script>

Я включаю его в свой заголовок, который может быть лучше для него, но, похоже, это решает проблему по крайней мере для меня. Это может повлиять на некоторую логику CSS, которую вы могли бы использовать для любых классов, которые вы указали специально для элементов FontAwesome, которые являются прямыми потомками других классов/идентификаторов, так что вы можете просто проверить, чтобы убедиться, что все ваши стилистики выглядят правильно, так как теперь они вложены <svg> внутри тега <i> вместо его замены.

В качестве альтернативы вы можете просто обернуть <i> самостоятельно. Например:

{this.state.loading === true ? <div><i className="fa-spin fas fa-sync"></i></div> ...

должно сработать.

ОБНОВЛЕНИЕ (10/10/18): Теперь в документации есть лучшее объяснение, почему это происходит в официальных документах, и объяснение того, как интегрировать этот FontAwesome с библиотекой javascript здесь. Метод автоматического вложения ваших тегов <i> теперь выполняется внутри тега скрипта для извлечения библиотеки JavaScript FontAwesome <script src="https://use.fontawesome.com/releases/v5.5.0/js/all.js" data-auto-replace-svg="nest"></script>. Также теперь есть официальная поддержка библиотеки FontAwesome React, которая также решает эту проблему.