Блокировки могут быть полезным инструментом, чтобы помочь пользователям найти свое место на вашем сайте или приложении. Я собираюсь построить один, используя Компонентный компонент шаблон и продемонстрировать, что с помощью реагирования Контекст и Порталы Мы можем использовать компонентное дерево для генерации ThradCrumbe Trail, которая не знает вашей иерархии или вашего местоположения внутри него.
Здесь будут некоторые передовые методы, но я не буду в подробности в отношении того, как Крючки , Контекст или Порталы Работа. Если вы чувствуете, что вам не хватает знаний в любой из этих областей, которые я бы предложил прочитать эти ссылки перед последующим продвижением.
Я начну с создания презентационные части компонента с Стильные компоненты Отказ Это мой предпочтительный выбор стайлинга, но не требуется для этого работать.
import React from 'react'; import { BrowserRouter, NavLink } from 'react-router-dom'; import styled from 'styled-components'; const Breadcrumb = ({ children }) => ( ); const Items = styled.ol` margin: 0; padding-left: 0; list-style: none; `; const BreadcrumbItem = ({ children, to, ...props }) => (- ); const Item = styled.li` display: inline; & + &::before { content: ''; display: inline-block; transform: rotate(15deg); border-right: 1px solid currentColor; height: 1em; margin: 0 8px -0.2em; } `; const ItemLink = styled(NavLink).attrs({ exact: true })` color: #36d; text-decoration: none; border-bottom: 1px solid transparent; &:hover { border-color: currentColor; } &.active { border: none; color: inherit; } `; const App = () => (
{children} ); One Two
Я мог бы остановиться здесь. Это компонент Charscrumb, и он тупой, однако, требует от каждой реализации потребителей вручную вручную жесткокодировать элементы Charbrem, которые предшествуют текущей странице или создают смарт-контейнер, который поддерживает запись вашей иерархии и вашу позицию в нем. Есть проще проще.
Порталы
Реагировать Порталы обеспечить возможность сделать компонент где угодно В DOM, чтобы мы могли представлять компонент за пределами своего нынешнего ветви в компонентном дереве. Это будет полезно, но это также делает что-то еще более полезное. При прохождении компонента через портал он не будет заменить Дети в узле, которые вы предоставляете, это будет Добавить к этому. Почему это актуально?
Трасса Chadowrumb состоит из списка ссылок на родительские страницы текущей страницы В иерархическом порядке Отказ
https://www.w3.org/TR/wai-aria-practices-1.1/#breadcrumb
При использовании пакета маршрутизатора, который поддерживает иерархию, такую как React Router , мы в конечном итоге с приказом иерархического исполнения наших страниц. Итак, если Панирум
Стал узлом портала в нашем заголовке приложений, Chader Croumbitem
S можно употреблять за пределами заголовка ветви на странице основы на странице и прилагается к нашему заголовозу в иерархическом порядке.
Следующие итерации на нашем существующем компоненте для достижения этого: https://codesandox.io/s/2-a-smarter-dumb-breadcrumb-jvi14?from-mbed.
Это здорово. Мы можем увидеть наши переименованные Chader Croumbitem
s (сейчас Chadrrumb
), оказываемые в Заголовок
компонент, даже если они употребляются вне этого. Но что здесь происходит?
const Breadcrumb = ({ children, to, ...props }) => { const [portalNode, setPortalNode] = useState(); useEffect(() => { setPortalNode(document.getElementById('breadcrumb')); }, []); return portalNode ? ReactDOM.createPortal(- , portalNode, ) : null; };
{children}
Useffect
Получает узел портала, когда компонент установлен и сохраняет его в локальном состоянии. Это заставит компонент повторно рендерировать и портал в Харботпортал
Поскольку он содержит элемент с идентификатором «Chad Charbrem».
К сожалению, мы можем только один экземпляр этого компонента на странице на данный момент, когда мы закончимся с конфликтующими идентификаторами «Chad Charbrem» на странице. Есть также возможность того, что наш потребитель уже дал что-то одно и то же удостоверение личности. Текущее решение не идеально и не очень глупо, но мы можем решить это с УСЭРЕФ
и контекст.
Контекст
Давайте внесем некоторые изменения в компонент портала, поэтому нам не нужно использовать ID
атрибут.
const BreadcrumbPortal = () => { const portalNodeRef = useRef(); const [, setPortalNode] = useBreadcrumbContext(); useEffect(() => { setPortalNode(portalNodeRef.current); }, []); return ( ); };
Я удалил ID
атрибут из Предметы
Компонент и использовал Ref
Вместо этого нужно получить свой узел DOM, но теперь нам нужен способ сообщить эту ценность для компонента предмета Chadercrumb, даже если он не будет потребляться как ребенок этого компонента. Это где usebreadcrumbcontext
крючок приходит.
Крючок позволит нашим компонентам Chadrumbum использовать некоторые общие состояния, предоставляемые ChadercrumbProvider
компонент без родительских/дочерних отношений между собой.
import React, { useContext } from 'react'; const Context = React.createContext(); const useBreadcrumbContext = () => { const context = useContext(Context); if (!context) { throw new Error('Missing BreadcrumbProvider.'); } return context; };
Крючок обернут существующие упреждающий текст
крючок и ошибаюсь, если ChadercrumbProvider
Мы собираемся создавать отсутствуют или иным образом возвращают предоставленную стоимость контекста.
const BreadcrumbProvider = ({ children }) => { const portalNodeState = useState(); return ({children} ); }; const rootElement = document.getElementById('root'); ReactDOM.render(, rootElement, );
ChadercrumbProvider
Первоначально предоставляет некоторое пустое состояние в качестве значения контекста и оборачивает наше приложение, так что любые компоненты ChadRumbum в приложении могут поделиться этим состоянием.
На данный момент эта настройка предполагает, что в нашем приложении будет только одна скоба, но если бы мы хотели больше, мы могли повторно использовать ChadercrumbProvider
на более низком уровне. Потребители будут потреблять контекст своего ближайшего провайдера, чтобы это дает нам гибкость иметь столько, сколько нам нравится без каких-либо конфликтующих идентификаторов.
Когда setportalnode
называется внутри Харботпортал
Выше он обновит Порталноде
Состояние в ChadercrumbProvider
Что будет обновлять значение контекста и вызвать переназначение любых детей, которые их потребляют. Поэтому любой Панирум
компоненты, которые существуют как (глубоко вложенные или немедленный) ребенок ChadercrumbProvider
сможет ссылаться на этот узел DOM и портал в него.
const Breadcrumb = ({ children, to, ...props }) => { const [portalNode] = useBreadcrumbContext(); return portalNode ? ReactDOM.createPortal(- , portalNode, ) : null; };
{children}
Когда сочетается с React Router Это дает нам все, что нам нужно, чтобы построить ThradCrumbe Trail, которая не знает вашей иерархии приложений.
Заключение
Мы можем сделать некоторые довольно мощные вещи при комбинировании крючков, порталов и составного компонента. Я настоятельно рекомендую экспериментировать еще с этими методами, это очень весело и может упростить потребительскую логику в вашем приложении.
Если здесь есть что-то, что я не очень хорошо объяснил (скорее всего 😛), или вы хотели бы обсудить дальше, тогда не стесняйтесь, чтобы бросить твит на @jjenzz Отказ