Передача реквизита компонентам, визуализированным динамически от объекта - PullRequest
0 голосов
/ 27 января 2020

У меня есть объект, полный компонентов:

const Icons = {
   // commonly used darksky icon names
   "clear-day": <ClearDayIcon />,
   "clear-night": <ClearNightIcon />,
   "rain": <RainMediumIcon />,
   "snow": <SnowIcon />,
   "sleet": <RainHeavyIcon />,
   "wind": <WindyDayIcon />,
   // etc..
}

Каждый компонент - это просто svg, обернутый как компонент реагирования. Но мне нужно, чтобы он получал реквизит из того места, где он вызывается, особенно className prop.

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

<WeatherIcon icon={icon} className="some-class" />

Где значок пропелла будет определять, какой компонент значка выбран. Итак, я попробовал это:

const WeatherIcon = props => Icons[ props.icon ]

Так что это работает частично, так как я могу написать <WeatherIcon icon={'clear-night'} />, и отображается правильный компонент. Тем не менее, нет никакого способа передать любой другой реквизит от моего WeatherIcon компонента через каждый Icon. Например, написание <WeatherIcon icon={'clear-night'} className="some-class" /> явно не пропускает className пропел (или любую другую опору) вниз к каждому отдельному компоненту. Я пытался сделать что-то вроде этого:

const Icons = {
   "clear-day": props => <ClearDayIcon {...props} />,
   "clear-night": props => <ClearNightIcon {...props} />,
   // etc..
}

Но это не работает, потому что теперь я возвращаю Component вместо <Component />. Я видел решения в вопросе Передача реквизитов динамически загружаемым компонентам , но все они предлагают вызывать компонент как { Icons['clear-day'](className: 'some-class', anotherProp: 'some-prop') }. Я чувствую, что это не очень элегантно. Должен быть способ записать его как <WeatherIcon icon={'some-icon'} className={'some-class'} someProp={'some-prop'} />, и правильно настроить фильтр реквизита. (Я понимаю, что все реквизиты будут отфильтровываться вплоть до моего SVG-компонента - это нормально). Я чувствую, что есть компонент высшего порядка, ожидающий написания здесь, но сейчас он ускользает от меня.

Спасибо за чтение

Ответы [ 2 ]

1 голос
/ 27 января 2020

Я не уверен на 100%, удовлетворит ли это ваше требование, но я, вероятно, попробую что-то подобное:

const Icons = {
   "clear-day": ClearDayIcon,
   "clear-night": ClearNightIcon,
   "rain": RainMediumIcon,
   "snow": SnowIcon,
   "sleet": RainHeavyIcon,
   "wind": WindyDayIcon,
   // etc..
}

const Icon = ({icon, ...rest}) => {
    const IconComponent = Icons[icon]

    if(!IconComponent) {
        // Or throw an exception maybe.
        // At least print some console warnings in development env.
        return null;
    }

    return <IconComponent {...rest} />
}

Таким образом, вы можете выбрать один из ваших компонентов Icon и передать любой поддержать это. И когда вы хотите использовать его, вы можете использовать его так:

// ...
<Icon icon="clear-day" className="some-class" />
// ...
0 голосов
/ 27 января 2020

Я понял, что это тоже работает - запишите объект, содержащий компоненты, как функцию реквизита, который возвращает объект. Тогда вы можете использовать {...props} в каждом компоненте:

const Icons = props => ({
   "clear-day": <ClearDayIcon {...props} />,
   "clear-night": <ClearNightIcon {...props} />,
   "rain": <RainMediumIcon {...props} />,
   etc.
})

Тогда компонент оболочки выглядит так:

const WeatherIcon = props => Icons(props)[ props.icon ]

Довольно просто - я знал, что был близок. Я не уверен, считается ли это компонентом более высокого порядка (HO C). Это является компонентом, который возвращает другой компонент на основе своих реквизитов с новыми прикрепленными реквизитами. Это считается как HO C?

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