Как получить доступ к реквизиту в функциональном HOC? - PullRequest
3 голосов
/ 07 октября 2019

У меня есть код, подобный следующему:

const HOC = (props, WrappedComponent) => {
    return (
       <>
          <WrappedComponent />
          <Icon className="props.iconStyles" />
       </>
     );
};

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

<HOC iconStyles="icon-stuff">
    <TheComponentIWantToWrap>
</HOC>

Как я могу написать это правильно, чтобы иметь возможность пропускать реквизит через? Я думаю, что мне может понадобиться использовать children и здесь, не уверен.

Ответы [ 4 ]

2 голосов
/ 07 октября 2019

Было бы что-то вроде этого.

const HOC = (WrappedComponent) => {

  const MyComponent = props => {
    return (
       <>
          <WrappedComponent {...props} />
          <Icon className={props.iconStyles} />
       </>
     );
   }
   
  return MyComponent;
};
2 голосов
/ 07 октября 2019

HOC - это функция, которая возвращает Component и обычно добавляет ей props. Вы должны разделить проблемы. Фактический HOC должен выглядеть следующим образом

const withFoo = Component =>{
    return props =>{
        return <Component injectedProps='foo' />
    }
}

И называться вот так

const Component = withFoo(({ injectedProps }) =>{
    return <jsx />
})

Если вы хотите объединить произвольный props, попробуйте также распространить propsпередано Component

const withFoo = Wrapped =>{
    return props =>{
        return <Wrapped injectedProps='foo' {...props}/>
    }
}

<Component propsToBeSpreaded='bar' />

Если вы предпочитаете, вы можете создать дополнительный слой.

  • HOC вводит некоторые реквизиты в Container
  • Container принимает произвольные props
  • Container рендеринга children

код

   const withHoc = Container =>{
        return () => <Container injected='foo' />
    }

    const Container = withHoc(({ children, injected, ...aditionalProps}) =>{
         return(
             <div {...aditionalProps}>
                 { children }
             </div>
         )
    })

и назовите его как

const FinalComp = () =>{
    return <Container foo='foo'> <span /> </Container>
}
2 голосов
/ 07 октября 2019

Компонент более высокого порядка будет возвращать другой компонент (в данном случае другую функцию). Компонент - это функция, которая возвращает JSX.

const HOC = (Component) => {
  return function WrappedComponent(props) {
    return (
       <>
          <Component {...props} />
          <Icon className="props.iconStyles" />
       </>
     );
  };
};
1 голос
/ 07 октября 2019

Вы все еще можете передать реквизиты вместе с Компонентом, который будет улучшен (в соответствии с вашим первоначальным подходом, который вы считаете неправильным). Это правильно, поскольку -

HOC не являются частью React API. Они вытекают из природы состава React.

Таким образом, ваше использование HOC -

const EnhancedComponent = higherOrderComponent(WrappedComponent, anyProps);

Обращает на себя внимание:

  1. Ваш HOC принимает Компонент ивозвращает Компонент (улучшенный или нет)

    const higherOrderComponent = (WrappedComponent, anyProps) => {
        return class extends React.Component {
            // Component body
        }
    } 

Не изменяйте оригинальный компонент. Используйте композицию. Передайте несвязанный реквизит обернутому компоненту.
    const higherOrderComponent = (WrappedComponent, anyProps) => {
        return class extends React.Component {
            render() {
                const { HOCProp, ...compProps } = this.props;
                return (
                    <WrappedComponent
                        ...compProps,
                        someProp={anyProps.someProp}
                    />
                );
            }
        }
    }

Учитывая все это, ваш HOC будет выглядеть так -

    const withWrappedIcon = (CompToWrap, iconStyle) => {
        return (
           <Icon className={iconStyle}>
              <CompToWrap />
           </Icon>
        );
    }
...