首页 > 解决方案 > 子组件功能不更新 DOM

问题描述

我有两个使用样式组件构建的组件,一个父组件和一个子组件。父组件将一些道具传递给子组件。如果需要,我可以添加样式,但我认为它们与我的问题无关。

家长

export const NavigationWrapper = ({ ariaLabel, expanded }) => {
  const [active, setActive] = React.useState(null);

  return (
    <NavWrapper
      aria-label={ariaLabel}
      data-testid="nav-wrapper"
      expanded={expanded}
    >
      <HeaderNavTab expanded={expanded} data-testid="header-nav-tab" href="/">
      </HeaderNavTab>
      <NavBodyTab
        text="Dashboard"
        Icon={Grid}
        expanded={expanded}
        active={active}
        setActive={setActive}
      />
      <NavBodyTab
        text="People"
        Icon={People}
        expanded={expanded}
        active={active}
        setActive={setActive}
        subNavMenu={[
          { name: "Link1" },
          { name: "Link2", subnav: ["sub link 1", "sub link 2"] },
        ]}
      />
      <NavBottomSpace data-testid="bottom-space" expanded={expanded} />
    </NavWrapper>
  );
};

子组件从父组件获取道具,并且它也有自己的钩子状态。

孩子

export const NavBodyTab = ({
  expanded,
  text,
  Icon,
  subNavMenu,
  active,
  setActive,
}) => {
  const [hovered, setHovered] = React.useState(false);
  const [opened, setOpened] = React.useState(null);
  const [subNavActive, setSubNavActive] = React.useState(null);
  const [subNavOpen, setSubNavOpen] = React.useState(false);
  const [subNavHovered, setSubNavHovered] = React.useState(false);


  const setActiveTab = (text) => {
    if (active === text) {
      setActive(null);
    } else {
      setActive(text);
    }
  };

  const setOpenTab = (text) => {
    if (opened === text) {
      setOpened(null);
    } else {
      setOpened(text);
    }
  };



  return (
    <div>
      <NavTab
        expanded={expanded}
        opened={opened}
        hovered={hovered}
        active={active}
        text={text}
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
        onFocus={() => {
          setActiveTab(text);
        }}
        onBlur={() => {
          setActiveFunction(subNavMenu);
        }}
        onClick={() => setOpenTab(text)}
        onKeyDown={handleKeyPress}
        data-testid={text + "-nav-tab"}
        tabIndex="0"
      >
        {expanded || (hovered && active === null) || active === text ? (
          <div>
            <IconHolder
              expanded={expanded}
              hovered={hovered}
              text={text}
              active={active}
              data-testid={text + "-icon-holder"}
            >
              <Icon
                fill={
                  hovered || active === text ? `${basic[100]}` : `${basic[500]}`
                }
                stroke={
                  hovered || active === text ? `${basic[100]}` : `${basic[500]}`
                }
                strokeWidth={"2"}
                height={"1.5rem"}
                width={"1.5rem"}
              />
            </IconHolder>
            {text}
            {expanded || subNavMenu ? (
              <ArrowHolder data-testid={text + "-arrow-holder"}>
                {opened === text && subNavMenu && expanded ? (
                  <ArrowDownward
                    data-testid={text + "-arrow-icon-down"}
                    fill={
                      hovered || active === text
                        ? `${basic[100]}`
                        : `${basic[500]}`
                    }
                    stroke={
                      hovered || active === text
                        ? `${basic[100]}`
                        : `${basic[500]}`
                    }
                    strokeWidth={"2"}
                    height={"1.5rem"}
                    width={"1.5rem"}
                  />
                ) : (
                  <ArrowForward
                    data-testid={text + "-arrow-icon"}
                    fill={
                      hovered || active === text
                        ? `${basic[100]}`
                        : `${basic[500]}`
                    }
                    stroke={
                      hovered || active === text
                        ? `${basic[100]}`
                        : `${basic[500]}`
                    }
                    strokeWidth={"2"}
                    height={"1.5rem"}
                    width={"1.5rem"}
                  />
                )}
              </ArrowHolder>
            ) : null}
          </div>
        ) : (
          <div>
            <IconHolder>
              <Icon
                fill={`${basic[500]}`}
                stroke={`${basic[500]}`}
                strokeWidth={"2"}
                height={"1.5rem"}
                width={"1.5rem"}
              />
            </IconHolder>
          </div>
        )}
      </NavTab>
    </div>
  );
};

我在这里剪掉了很多绒毛,但这是基本想法。现在我正在尝试纠正一个测试,该测试将检查 navTab 样式是否正确更新。

我在 navTab 上有一些样式:

const NavTab = styled.div`
  height: 3.5rem;
    ${(props) =>
      props.hovered && props.active === null
        ? `width: 16.25rem; color: ${basic[100]};`
        : null}
  ${(props) =>
    props.active === props.text
      ? `width: 16.25rem; background-color: #434e59; color: ${basic[100]}; outline: none;`
      : null}
`;

当用户将鼠标悬停在 NavTab 上时,我应该能够测试样式是否发生了变化。

  test("mouse over", () => {
    const expanded = false;
    const setExpanded = jest.fn();
    React.useState = jest.fn(() => [expanded, setExpanded]);
    const { getByTestId, queryByTestId, debug } = render(
      <NavigationWrapper
        ariaLabel="navigation wrapper"
        expanded={false}
      />
    );
    const navTab = getByTestId("People-nav-tab");

    expect(navTab).toHaveStyleRule("width", "5rem");

    fireEvent.mouseEnter(navTab);

    expect(navTab).toHaveStyleRule("width", "16.25rem");
  });

最后一次测试失败。我曾尝试使用debug()来查看 navTab 组件如何随悬停而变化,但没有任何变化。我还使用调试来查看 navTab 如何随着焦点的变化也没有变化。我也尝试过fireEvent单击 navTab 并且再次没有更改调试器输出。

我真的很困惑我应该如何测试这些风格和状态的变化。

标签: styled-componentsreact-testing-library

解决方案


推荐阅读