reactjs 如何改变图标的状态只有在React?

watbbzwu  于 2022-12-18  发布在  React
关注(0)|答案(1)|浏览(145)

我正在创建可重用的React accordion 组件,需要改变菜单的图标。首先,箭头右图标应显示时,按钮是不活动的,当用户点击它,链接列表应显示,图标应得到改变为箭头向下。
到目前为止,我管理,使它显示,但不是在我点击菜单后,他们两个都显示在一起,而不是改变。
我用Storybook来显示,用样式化的组件来显示样式。下面是代码以及它们在Storybook中的外观:

import { string, oneOf, func, bool } from "prop-types"
import React, { useState } from 'react';
import Icon, { icons } from "design-system/components/icon"
import * as Styled from "./Button.styled"

const Button = ({href,text,iconactive,iconinactive,variant,color,size,
}) => {
const [isActive, setIsActive] = useState(false);
const [isinActive, setIsInActive] = useState(false);
return (
  <Styled.Component
  color={color}
  size={size}
  >
    <Styled.Text
    variant={variant}
    color={color}
    size={size}
    href={href}
    onClick={() => setIsActive(!isActive)}>
      {text}
    </Styled.Text>
    {isActive && <Styled.Icon>
        <Icon name={iconactive} size={size} color={color}/>
    </Styled.Icon>}
    >
    {isinActive &&
     <Styled.Icon>
        <Icon name={iconinactive} size={size} color={color}/>
    </Styled.Icon>}
    {isActive && <Styled.Links size={size} color={color}>
      {href} {href}
      </Styled.Links>}
  </Styled.Component>
);
};

Button.propTypes = {
  text: string.isRequired,
  href: string,
  iconactive: oneOf(Object.keys(icons)),
  variant: oneOf(["fill", "border", "text", "textLine"]),
  color: oneOf(["primary", "black", "white"]),
  size: oneOf(["small", "medium", "large"]),
  active: bool,
  onClick: func,
}

Button.defaultProps = {
  href: null,
  iconactive: null,
  isinActive: null,
  variant: "fill",
  color: "primary",
  size: "medium",
  active: null,
  onClick: null,
}

export default Button

storybook:

import { Meta, Canvas, Story, ArgsTable } from "@storybook/addon-docs"

import Button from "design-system/components/button"
import Icon from "design-system/components/icon"

<Meta title="Components/Button" component={Button} />

# Button

Button can be a regular button, a link or a navigation link.

<Canvas>
  <Story
    name="Overview - button icon end"
    args={{
      text: "Inactive",
      iconactive: "arrowdown",
      iconinactive: "arrowright",
      variant: "fill",
      size: "small",
      href: "Link",
    }}
  >
    {Template.bind()}
  </Story>
    {Template.bind()}
  </Story>
</Canvas>

<ArgsTable />

export const Template = (args) => <Button {...args} />

Button Styled:

import styled from "@emotion/styled"
import theme from "design-system/theme"

const sizes = {
  small: {
    typography: theme.typography.desktop.bodySmall,
    padding: "8px 32px",
  },
  medium: {
    typography: theme.typography.desktop.h5,
    padding: "10px 40px",
  },
  large: {
    typography: theme.typography.desktop.h4,
    padding: "12px 48px",
  },
}

const colors = {
  primary: {
    mainColor: theme.colors.primary[500],
    filledText: theme.colors.neutrals[100],
  },
  black: {
    mainColor: theme.colors.grey[600],
    filledText: theme.colors.neutrals[100],
  },
  white: {
    mainColor: theme.colors.neutrals[100],
    filledText: theme.colors.primary[300],
  },
}

export const Component = styled.a`
  ${({ size }) => sizes[size].typography};
  letter-spacing: -0.02em;
  border-radius: 30px;
  cursor: pointer;
  text-decoration: none;
  padding: ${({ size }) => sizes[size].padding};
  
`
export const Text = styled.span`
color: ${({ variant, color }) =>
variant === "fill" ? colors[color].mainColor : "black"};
  font-weight: bold;
  text-decoration: none;
  padding: 20px 0px;
  width: 342px;
  height: 64px;
  border-radius: 10px;
}`

export const Icon = styled.span`
color: ${({ variant, color }) =>
variant === "fill" ? colors[color].mainColor : "black"};
`
export const Links = styled.span`
display: block;
flex-direction: column;
align-items: flex-start;
padding: 5px;
${({ size }) => sizes[size].typography};
letter-spacing: -0.02em;
gap: 3rem;
border-radius: 30px;
cursor: pointer;
text-decoration: none;
padding: ${({ size }) => sizes[size].padding};
color: ${({ variant, color }) =>
  variant === "fill" ? colors[color].filledText : "black"};
`

```[![here state is inactive][1]][1]
[![here state is active][2]][2]

  [1]: https://i.stack.imgur.com/iHrGQ.png
  [2]: https://i.stack.imgur.com/ikite.png

Could you please be so kind to advsie how could I implement the change of the icon over click in this componennt ?

Thank you in advance,

regards,
Emilia
p8h8hvxi

p8h8hvxi1#

您使用的状态太多!!!
最好去掉isinActive状态,只使用isActive,把它看作是一个在开和关之间切换的开关。
您的组件也可以按如下方式重新排列:

import { string, oneOf, func, bool } from "prop-types"
import React, { useState } from 'react';
import Icon, { icons } from "design-system/components/icon"
import * as Styled from "./Button.styled"

const Button = ({
  href,
  text,
  iconactive,
  iconinactive,
  variant,
  color,
  size,
}) => {
  const [isActive, setIsActive] = useState(false);
  const currentIcon = isActive ? iconactive : iconinactive;
  return (
    <Styled.Component
      color={color}
      size={size}
    >
      <Styled.Text
      variant={variant}
      color={color}
      size={size}
      href={href}
      onClick={() => setIsActive(!isActive)}>
        {text}
      </Styled.Text>
      <Styled.Icon>
          <Icon name={currentIcon} size={size} color={color}/>
      </Styled.Icon>
      {isActive && (
        <Styled.Links size={size} color={color}>
          {href} {href}
        </Styled.Links>
      )}
    </Styled.Component>
  );
}

Button.propTypes = {
  text: string.isRequired,
  href: string,
  iconactive: oneOf(Object.keys(icons)),
  variant: oneOf(["fill", "border", "text", "textLine"]),
  color: oneOf(["primary", "black", "white"]),
  size: oneOf(["small", "medium", "large"]),
  active: bool,
  onClick: func,
}

Button.defaultProps = {
  href: null,
  iconactive: null,
  isinActive: null,
  variant: "fill",
  color: "primary",
  size: "medium",
  active: null,
  onClick: null,
}

export default Button

相关问题