Якорь меню React Material-UI потерян из-за повторного отображения окна реакции - PullRequest
0 голосов
/ 08 января 2020

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

Recording

Вопрос связан с Якорь меню Uact-материала React, сломанный списком реагирующих окон , но имеет больше HO C. Код указан здесь . Я sh Я мог бы использовать свои коды и ящик для демонстрации, но react-measure продолжает расти.

function App() {
  const [anchorEl, setAnchorEl] = useState(null);

  const openMenu = React.useCallback(e => {
    e.stopPropagation();
    setAnchorEl(e.currentTarget);
    console.log("target", e.currentTarget);
  }, []);

  const handleClose = () => {
    setAnchorEl(null);
  };

  const [items, setItems] = React.useState([]);
  const isItemLoaded = index => {
    const c = index < items.length;
    // console.log("isItemLoaded", index, c);
    return c;
  };
  const loadMoreItems = (startIndex, stopIndex) => {
    console.log("loadMoreItems", startIndex, items);
    setItems(items.concat(Array(10).fill({ name: "1", size: startIndex })));
  };

  const innerET = React.forwardRef((props, ref) => (
    <div ref={ref} {...props} />
  ));

  const Row = React.useCallback(
    ({ index, style }) => {
      console.log("Row", items, index);
      return items[index] ? (
        <ListItem style={style} key={index}>
          <Button variant="contained" color="primary" onClick={openMenu}>
            Row {index}: {items[index].size}
          </Button>
        </ListItem>
      ) : null;
    },
    [items, openMenu]
  );

  const innerListType = React.forwardRef((props, ref) => (
    <List ref={ref} {...props} />
  ));

  return (
    <div className="App">
      <div className="ceiling">Something at top</div>

      <div className="interest">
        <Menu anchorEl={anchorEl} onClose={handleClose} />
        <Measure bounds offset>
          {({ measureRef, contentRect }) => {
            const height = Math.min(
              contentRect && contentRect.offset
                ? document.getElementById("root").getBoundingClientRect()
                    .height - contentRect.offset.top
                : itemSize * items.length,
              itemSize * items.length
            );
            console.log(
              "bounds",
              height,
              contentRect.bounds,
              contentRect.offset
            );
            return (
              <div>
                <div />
                <div ref={measureRef} className="measurement">
                  <InfiniteLoader
                    isItemLoaded={isItemLoaded}
                    itemCount={itemCount}
                    loadMoreItems={loadMoreItems}
                  >
                    {({ onItemsRendered, ref }) => (
                      <FixedSizeList
                        height={height}
                        width={
                          contentRect.bounds !== undefined &&
                          contentRect.bounds.width !== undefined
                            ? contentRect.bounds.width
                            : -1
                        }
                        itemCount={itemCount}
                        itemSize={itemSize}
                        onItemsRendered={onItemsRendered}
                        ref={ref}
                        innerElementType={innerET}
                      >
                        {Row}
                      </FixedSizeList>
                    )}
                  </InfiniteLoader>
                </div>
              </div>
            );
          }}
        </Measure>
      </div>
    </div>
  );
}

Насколько я понимаю, эффект ряби вызовет повторный рендеринг в окне с первым щелчком мыши. Более того, второй щелчок после повторного рендеринга после нажатия не вызовет повторного рендеринга. Это кажется мне еще более странным.

РЕДАКТИРОВАТЬ: я исправил первую песочницу. И при использовании списка Material UI эта проблема воспроизводима. https://codesandbox.io/s/blissful-butterfly-qn3g7 Таким образом, проблема заключается в использовании свойства innerElementType.

1 Ответ

0 голосов
/ 10 января 2020

Оказывается, нужен крюк.

  const innerListType = React.useMemo(() => {
    return React.forwardRef((props, ref) => (
      <List component="div" ref={ref} {...props} />
    ));
  }, []);

Чтобы исправить мои проблемы, крючки для обработки событий необходимо обрабатывать более осторожно.

...