profile
viewpoint

Ask questionsОтличный доклад!!

Я считаю, что твоя библиотека выглядит очень замечательно! Я тут за пол часика наколхозил наивную реализацию в 11 строчек кода...

import { createPortal } from "preact/compat";
export const Area = ({ name }) => <div slot={name} />;
export const Content = ({ children, name }) => {
  const selector = `[slot="${name}"]`;
  const container = document.querySelector(selector);
  if (!container) {
    console.log(`${selector} notFound`);
    return null;
  }
  return createPortal(<div>{children}</div>, container);
};
  1. Пытался ли ты решить это с порталами? Если да, интересно узнать недостатки
  2. Я предполагаю, что мой код имеет проблемы с производительностью/лишними элементам_там_где_не_нужно. Как считаешь, можно ли их решить или бросить эту затею ? :)
everdimension/react-area

Answer questions everdimension

Привет! Спасибо за интерес к библиотеке :)

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

Твой пример не будет работать по следующим причинам

  1. Самый простой кейс —

    function App() {
      return (
        <>
          <RenderArea name="1" />
          <Content name="1">hello</Content>
        </>
      );
    }
    

    Мы просто ничего не увидим на экране. Дело в том, что RenderArea и Content рендерятся одновременно. На момент первого рендера RenderArea ещё не успевает замаунтить дом-ноду, а Content уже её ищет. Поэтому пока по внешним причинам не произойдёт ререндер, страничка будет пустая. В идеале же концепция паттерна такая, что нам должно быть вообще всё равно, в каком порядке рендерить RenderArea и Content. То есть если мы рендерим <Content name="1" />, но на странице на данный момент нет соответвующей RenderArea, то ничего не должно ломаться, мы просто должны не видеть Content. Но как только <RenderArea name="1" /> отрендерится, мы должны увидеть содержание Content, несмотря на то, что в этот момент ререндер родителя Content мог быть не вызван.

  2. Допустим, первую проблему мы решили через какую-либо систему подписок и уведомлений. Вторая проблема — рендеринг нескольких Content в одну RenderArea, при этом Content рендерится по кондишну:

    function App() {
      const [shouldShow, toggle] = setState(true);
      return (
        <>
          <button onClick={() => toggle(!shouldShow)}>toggle</button>
          <RenderArea name="1" />
          {shouldShow ? <Content name="1">hello</Content> : null}
          <Content name="1">world</Content>
        </>
      );
    }
    

    В этом случае, к сожалению, не будет соблюдаться порядок отображения. Сначала мы увидим "helloworld", затем "world", затем "worldhello". Если есть идеи, как решить эту проблему через порталы, мне будет очень интересно их послушать.

  3. Лишний dom-элемент. При использовании порталов элемент <RenderArea /> вынужден рендерить конкретный dom-элемент. Скорее всего это будет div. Но можно и параметризировать. В любом случае это не то, что мы хотим. По задумке <RenderArea /> не должна создавать лишний dom-элемент вообще.

useful!

Related questions

No questions were found.
Github User Rank List