React HO C, работающий на некоторых, но не на других компонентах - PullRequest
2 голосов
/ 15 апреля 2020

Я использую компонент HO C, чтобы связать действие со многими различными типами элементов, включая SVG-ячейки, которые, когда onClick привязан нормально, работают, но когда я использую свой HO C, это возвращает непредвиденные результаты.

Пример минимальной воспроизводимости: https://codesandbox.io/s/ecstatic-keldysh-3viw0

Компонент HO C:

export const withReport = Component => ({ children, ...props }) => {
    console.log(Component); //this only prints for ListItem elements for some reason

    const { dispatch } = useContext(DashboardContext);

    const handleClick = () => {
        console.log('clicked!'); //even this wont work on some.
        const { report } = props;
        if (typeof report === "undefined") return false;

        dispatch({ type: SET_ACTIVE_REPORT, activeReport: report });
        dispatch({ type: TOGGLE_REPORT });
    };

    return (
        <Component onClick={handleClick} {...props}>
            {children}
        </Component>
    );
};

Использование при работе:

const ListItemWIthReport = withReport(ListItem); //list item from react-mui
{items.map((item, key) => (
    <ListItemWithReport report={item.report} key={key} button>
        {/* listitem children*/}
    </ListItemWithReport>
))}

Использование не работает:

const BarWithReport = withReport(Bar); //Bar from recharts
{bars.map((bar, index) => (
    <BarWithReport
        report={bar.report}
        key={index}
        dataKey={bar.name}
        fill={bar.fill}
    />
))}

ListItem работает на 100%, как и ожидалось, однако столбцы не будут отображаться внутри BarChart. Точно так же с PieChart ячейки будут фактически отображаться, с правильными размерами в соответствии с их значениями, однако, реквизиты, подобные «заливке», по-видимому, не проходят вниз.

Я неправильно использую HO C? Я не вижу опции, кроме HO C для внутренних диаграмм, так как многие типы элементов будут считаться недействительными HTML?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2020

Возможно, вы имеете дело с компонентами, которые имеют важные свойства c, которые необходимо поднять в обернутый компонент или реализовать пересылку ссылок для того, чтобы их родительские компоненты могли их обрабатывать. Очень важно получить эти части, особенно при упаковке компонентов, в которых вы не знаете их внутренности. Этот компонент Bar, например , имеет некоторые свойства c . Ваш HO C заставляет их исчезнуть.

Вот как вы можете поднять этих участников c:

import hoistNonReactStatic from 'hoist-non-react-statics';

export const withReport = Component => {
  const EnhancedComponent = props => {
    const { dispatch } = useContext(DashboardContext);

    const handleClick = () => {
      const { report } = props;
      if (typeof report === "undefined") return false;

      dispatch({ type: SET_ACTIVE_REPORT, activeReport: report });
      dispatch({ type: TOGGLE_REPORT });
    };

    return (
      <Component onClick={handleClick} {...props}/>
    );
  };

  hoistNonReactStatic(EnhancedComponent, Component);
  return EnhancedComponent;
};

Документы по поднятию статики и пересылке ссылок можно найти в этом удобное руководство по HOC .

Возможно, есть некоторые библиотеки, которые позаботятся обо всех этих деталях для вас. Один, addhoc, работает следующим образом:

import addHOC from 'addhoc';

export const withReport = addHOC(render => {
  const { dispatch } = useContext(DashboardContext);

  const handleClick = () => {
    const { report } = props;
    if (typeof report === "undefined") return false;

    dispatch({ type: SET_ACTIVE_REPORT, activeReport: report });
    dispatch({ type: TOGGLE_REPORT });
  };

  return render({ onClick: handleClick });
});

Конечно, если родительский компонент проверяет дочерние компоненты по типу явно , то вы выиграли ' не сможет использовать HOC вообще. На самом деле, похоже, что проблема повторных выпусков. Здесь вы можете видеть, что диаграмма определена в терминах дочерних компонентов , которые затем явно ищут по типу .

1 голос
/ 15 апреля 2020

Я думаю, что ваш HO C недействителен, потому что не каждый компонент-обертка (например, HTML элемент) в основном кликабелен. Возможно, этот отрывок может прояснить то, что я пытаюсь сказать:

const withReport = Component => (props) => {
  const handleClick = () => console.log('whatever')

  // Careful - your component might not support onClick by default
  return <Component onClick={handleClick}  {...props} />
  // vs.
  return <div onClick={handleClick} style={{backgroundColor: 'green'}}>
    <Component {...props} />

    {props.children}
  </div>
}

// Your import from wherever you want
class SomeClass extends React.Component {
  render() {
    return <span onClick={this.props.onClick}>{this.props.children}</span>
    // vs.
    return <span style={{backgroundColor: 'red'}}>
      {
        // Careful - your imported component might not support children by default
        this.props.children
      }
    </span>
  }
}

const ReportedListItem = withReport(SomeClass)

ReactDOM.render(<ReportedListItem>
  <h2>child</h2>
</ReportedListItem>, mountNode)

Вы можете иметь верх или низ (разделенные vs.), но не пересекаться. HO C с использованием второго возврата (контролируемый компонент-обертка), безусловно, больше экономит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...