React 组件函数调用仅更新一个组件实例

发布于 2025-01-19 09:15:41 字数 1857 浏览 0 评论 0原文

我有一个名为 RightTab 的组件,如下所示

const RightTab = ({ data }) => {
  return (
    <div className="RightTab flex__container " onClick={data.onClick}>
      <img src={data.icon} alt="Dashboard Icon" />
      <p className="p__poppins">{data.name}</p>
      {data.dropDown === true ? (
        <div className="dropdown__icon">
          <img src={Assets.Arrow} alt="Arrow" />
        </div>
      ) : (
        <div className="nothing"></div>
      )}
    </div>
  );
};

export default RightTab;

该选项卡在其 CSS 中有一个活动状态,如下所示,

.RightTab.active {
  background-color: var(--primaryGreen);
}

正如您所看到的,当添加活动类时它会更改颜色。我在父组件中有一个数组,我将其作为 props 传递给子组件。这是数组

const dataArray = [
  {
    name: "Dashboard",
    icon: Assets.Dashboard,
    dropDown: false,
    onClick: handleDashBoardClick,
  },
  {
    name: "Inventory",
    icon: Assets.Inventory,
    dropDown: true,
    onClick: handleInventoryClick,
  },
  {
    name: "Reports",
    icon: Assets.Reports,
    dropDown: true,
    onClick: handleReportsClick,
  },
];

这是我传递道具的方式。

  <RightTab data={dataArray[0]} />
  <RightTab data={dataArray[1]} />
  <RightTab data={dataArray[2]} />

传递到组件中的 data 属性是一个对象,其中包含函数调用作为其属性之一,如下所示。我在子组件的主容器上有一个 onclick 属性,它应该调用相应的函数。

该函数是添加活动类以使背景改变颜色的函数。但是,每次我单击该组件时它只会更改第一次出现的背景。您可能已经注意到,我调用该组件三次。无论我点击哪个组件,只有第一个组件的背景发生变化

这是 prop 对象上的函数的示例。

const handleDashBoardClick = () => {
  const element = document.querySelector(".RightTab");
  element.classList.toggle("active");
};

我不明白我做错了什么。我还可以使用什么其他方法?

I have a component called RightTab like this

const RightTab = ({ data }) => {
  return (
    <div className="RightTab flex__container " onClick={data.onClick}>
      <img src={data.icon} alt="Dashboard Icon" />
      <p className="p__poppins">{data.name}</p>
      {data.dropDown === true ? (
        <div className="dropdown__icon">
          <img src={Assets.Arrow} alt="Arrow" />
        </div>
      ) : (
        <div className="nothing"></div>
      )}
    </div>
  );
};

export default RightTab;

The tab has an active state in its CSS like this

.RightTab.active {
  background-color: var(--primaryGreen);
}

as you have seen it changes the color when an active class is added. I have an array in the parent component that I pass down to the child component as props. Here is the array

const dataArray = [
  {
    name: "Dashboard",
    icon: Assets.Dashboard,
    dropDown: false,
    onClick: handleDashBoardClick,
  },
  {
    name: "Inventory",
    icon: Assets.Inventory,
    dropDown: true,
    onClick: handleInventoryClick,
  },
  {
    name: "Reports",
    icon: Assets.Reports,
    dropDown: true,
    onClick: handleReportsClick,
  },
];

Here is how I pass the props down.

  <RightTab data={dataArray[0]} />
  <RightTab data={dataArray[1]} />
  <RightTab data={dataArray[2]} />

The data prop passed into the component is an object containing a function call as one of its properties like this. I have an onclick attribute on the child components' main container that is supposed to call the respective function.

The function is what adds the active class to make the background change color. However each time I click on the component it only changes the background of the first occurrence. And as you may have noticed I call the component thrice. No matter which component I click only the first ones background changes.

Here is an example of the function that is on the prop object.

const handleDashBoardClick = () => {
  const element = document.querySelector(".RightTab");
  element.classList.toggle("active");
};

I don't get what I'm doing wrong. What other approach can I use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黑色毁心梦 2025-01-26 09:15:41

尽管您使用3次组件,但这并不意味着您在其中一个组件中进行的更改将反映在另一个2中,除非您专门使用传递给所有3个的状态参数。

另外,不建议添加活动类的方式,因为您将React与纯JS混合以处理CSS类名称。

我建议使用一个单击处理程序,该处理程序可以为所有n righttab组件切换活动类:

const MainComponent = () => {
  const [classNames, setClassNames] = useState([]);
  
  const handleClick = (name) => 
  {
    const toggledActiveClass = classNames.indexOf('active') === -1
      ? classNames.concat(['active'])
      : classNames.filter((className) => className !== 'active');
      
    setClassNames(toggledActiveClass);
    
    switch (name) {
      case 'Dashboard';
        // do something
        break;
        
        case 'Inventory':
        // ....
        break;
    }
  }
  
  const dataArray = [
    {
      name: "Dashboard",
      icon: Assets.Dashboard,
      dropDown: false,
      onClick: handleClick.bind(null, 'Dashboard'),
    },
    {
      name: "Inventory",
      icon: Assets.Inventory,
      dropDown: true,
      onClick: handleClick.bind(null, 'Inventory'),
    },
    {
      name: "Reports",
      icon: Assets.Reports,
      dropDown: true,
      onClick: handleClick.bind(null, 'Reports'),
    },
  ];

  return (
    <>
      {dataArray.map((data) => 
        <RightTab key={data.name} 
                  data={data} 
                  classNames={classNames} />)}
    </>
  );
};

const RightTab = ({ data, classNames }) => {
  return (
    <div className={classNames.concat(['RightTab flex__container']).join(' ')} 
         onClick={data.onClick}>
      <img src={data.icon} alt="Dashboard Icon" />
      <p className="p__poppins">{data.name}</p>
      {data.dropDown === true ? (
        <div className="dropdown__icon">
          <img src={Assets.Arrow} alt="Arrow" />
        </div>
      ) : (
        <div className="nothing"></div>
      )}
    </div>
  );
};

Although you use the component 3 times, it doesn't mean that a change you make in one of the components will be reflected in the other 2, unless you specifically use a state parameter that is passed to all 3 of them.

Also, the way you add the active class is not recommended since you mix react with pure js to handle the CSS class names.

I would recommend having a single click handler that toggles the active class for all n RightTab components:

const MainComponent = () => {
  const [classNames, setClassNames] = useState([]);
  
  const handleClick = (name) => 
  {
    const toggledActiveClass = classNames.indexOf('active') === -1
      ? classNames.concat(['active'])
      : classNames.filter((className) => className !== 'active');
      
    setClassNames(toggledActiveClass);
    
    switch (name) {
      case 'Dashboard';
        // do something
        break;
        
        case 'Inventory':
        // ....
        break;
    }
  }
  
  const dataArray = [
    {
      name: "Dashboard",
      icon: Assets.Dashboard,
      dropDown: false,
      onClick: handleClick.bind(null, 'Dashboard'),
    },
    {
      name: "Inventory",
      icon: Assets.Inventory,
      dropDown: true,
      onClick: handleClick.bind(null, 'Inventory'),
    },
    {
      name: "Reports",
      icon: Assets.Reports,
      dropDown: true,
      onClick: handleClick.bind(null, 'Reports'),
    },
  ];

  return (
    <>
      {dataArray.map((data) => 
        <RightTab key={data.name} 
                  data={data} 
                  classNames={classNames} />)}
    </>
  );
};

const RightTab = ({ data, classNames }) => {
  return (
    <div className={classNames.concat(['RightTab flex__container']).join(' ')} 
         onClick={data.onClick}>
      <img src={data.icon} alt="Dashboard Icon" />
      <p className="p__poppins">{data.name}</p>
      {data.dropDown === true ? (
        <div className="dropdown__icon">
          <img src={Assets.Arrow} alt="Arrow" />
        </div>
      ) : (
        <div className="nothing"></div>
      )}
    </div>
  );
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文