Мне нужен способ дать пользователям моего веб-приложения React возможность делать глубокие ссылки на отдельные компоненты (помеченные deeplinkKey
prop) на любой странице. Пользователь будет go на URL, который включает в себя ключ компонента. Затем приложение сделает видимым компонент (ы), в которых deeplinkKey
prop соответствует данному ключу only , скрывая все остальные элементы с deeplinkKey
реквизитом. (Элементы без deeplinkKey
prop всегда показывались бы.)
В настоящее время у меня есть компонент-обертка, который показывает / скрывает элементы в своем дочернем дереве на основе белого списка (включен ниже). Однако элемент-обертка не может видеть неопределяемые дочерние элементы.
Как разрешить пользователю ссылаться на скрытые элементы, такие как 'resourceA' в этом примере, и <DeeplinkWrapper>
отображать их:
let condition = true;
<DeeplinkWrapper deeplinkWhitelist=['resourceA']>
<Root>
{condition ?
<ParentElement1>
<Element deeplinkKey='someResource' />
</ParentElement1>
:
<ParentElement2>
<Element deeplinkKey='resourceA' />
</ParentElement2>
}
</Root>
</DeeplinkWrapper>
/*
Desired "deep-linked" render:
<Root>
<ParentElement2>
<Element deeplinkKey='resourceA' />
</ParentElement2>
</Root>
*/
Вот моя обертка. Он работает на основе этих правил:
// Any child element of <DeeplinkWrapper> will show if:
// The whitelist array is empty
// The child is pure text or null
// The child does not have the 'deeplinkKey' prop
// The child's 'deeplinkKey' prop exists and its value is in the whitelist array
// Any child element of <DeeplinkWrapper> will be hidden if:
// It's a child of a hidden parent
// The child's 'deeplinkKey' prop exists, but is not in the whitelist
// The child's 'deeplinkKey' prop exists, but is undefined, e.g. <span deeplinkKey>Text</span>
export default function DeeplinkWrapper({ children, whitelist = [] }) {
const showWhitelistedComponents = (children, fn) => {
return React.Children.map(children, child => {
const isReactElement = React.isValidElement(child);
const doShow = !isReactElement || !child.props.deeplinkKey || whitelist.indexOf(child.props.deeplinkKey) !== -1;
if (!isReactElement) {
return doShow ? child : null;
}
if (child.props.children) {
child = React.cloneElement(child, {
children: showWhitelistedComponents(child.props.children, fn)
});
}
return doShow ? fn(child) : null;
});
}
return (
<React.Fragment>
{whitelist.length === 0 ? React.Children.map(children, child => child) : showWhitelistedComponents(children, child => child)}
</React.Fragment>
)
}