Предупреждение о типе компонентов React Compound

У меня есть простой составной компонент с кучей статических подкомпонентов:

// @flow
import React, { Component, Children } from 'react';

type Props = {
  children: React.ChildrenArray<React.Node> | React.Node,
}

class Toggle extends Component<Props> {
  static On = props => (props.on ? props.children : null);

  static Off = props => (props.on ? null : props.children);

  static Button = props => (
    <button
      onClick = {props.toggle}
      type = "button"
      style = {{ display: 'inline-block' }}
    >
      <pre>{JSON.stringify(props.on, null, 2)}</pre>
    </button>
  );

  state = { on: false }

  toggle = () => {
    this.setState(
      ({ on }) => ({ on: !on }),
      // maybe this.props.someCallback
      () => console.info(this.state.on),
    );
  }

  render() {
    return Children.map(
      this.props.children,
      childElem => React.cloneElement(childElem, {
        on: this.state.on,
        toggle: this.toggle,
      }),
    );
  }
}

export default Toggle;

Предупреждение появляется, когда я пытаюсь поместить некоторые другие элементы в область Toggle children. Например:

<Toggle>
  <Toggle.On>On</Toggle.On>
  <span /> <-- this is savage
  <Toggle.Button />
  <Toggle.Off>Off</Toggle.Off>
</Toggle>

Все работает, но мой тип потока предупреждает меня об этом интервале следующим образом:

Warning: Received `false` for a non-boolean attribute `on`.....
Warning: Invalid value for prop `toggle` on <span> tag....

Как я могу усмирить эту противную девушку?

Я думаю, что props.children включает тег <span />, поэтому вы получаете это предупреждение.

Wen W 15.07.2018 16:57

Да, конечно, но как я могу обработать это предупреждение? Мне, возможно, понадобятся какие-то другие теги внутри моего составного элемента, но все они вызовут это предупреждение.

WebArtisan 15.07.2018 17:07

Просто сделай это? Статический on = props => (props.on? True: null)? Что вы пытаетесь сделать, присваивая дочерним элементам логическое значение?

Wen W 15.07.2018 17:20

Извините, код не закончился. Детей нужно назначить отдельно.

Wen W 15.07.2018 17:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
251
2

Ответы 2

Спасибо, ребята, я думаю, правильное решение - просто проверить, правильный ли тип смонтированного узла, в противном случае - просто клонировать узел с обычными реквизитами узла:

// @flow
import React, { Component, Children } from 'react';

type Props = {
  children: React.ChildrenArray<React.Node> | React.Node,
}

class Toggle extends Component<Props> {
  static On = props => (props.on ? props.children : null);

  static Off = props => (props.on ? null : props.children);

  static Button = props => (
    <button
      onClick = {props.toggle}
      type = "button"
      style = {{ display: 'inline-block' }}
    >
      <pre>{JSON.stringify(props.on, null, 2)}</pre>
    </button>
  );

  state = { on: false }

  toggle = () => {
    this.setState(
      ({ on }) => ({ on: !on }),
      // maybe this.props.someCallback
      () => console.info(this.state.on),
    );
  }

  // Checking here
  allowedTypes = ({ type }) => {
    return [
      (<Toggle.On />).type,
      (<Toggle.Off />).type,
      (<Toggle.Button />).type,
    ].includes(type);
  }

  render() {
    return Children.map(
      this.props.children,
      (childElem) => {
        const elemProps = this.allowedTypes(childElem) ? {
          on: this.state.on,
          toggle: this.toggle,
        } : childElem.props;
        return React.cloneElement(childElem, elemProps);
      },
    );
  }
}

export default Toggle;

Вы также можете сделать это, просто поместив компоненты в список и проверив их тип внутри .map, добавив настраиваемые реквизиты или иным образом просто вернув исходный дочерний элемент.

const allowedTypes = [ToggleOn, ToggleOff, ToggleButton]

return React.Children.map(props.children, child => {
  if (allowedTypes.includes(child.type)) {
    return React.cloneElement(child, {on, toggle})
  }
  return child
  })
}

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