繁体   English   中英

单击 React 组件时,如何隐藏该组件的所有其他实例?

[英]When a react component is clicked, how do I hide all other instances of that component?

我正在处理我的投资组合,因为我目前是一名失业的初级人员,我发现几乎不可能让一个组件的所有实例在该组件的另一个实例的交互(单击)时消失。

我基本上有用 react-card-flip 创建的卡片; 当用户点击其中一张卡片时,它会翻转并扩大尺寸以显示更多详细信息。 这些卡片有多个实例是通过对 axios GET 请求 api.github 创建的...我没有设法开始工作的部分是使卡片的 rest 在单击的卡片展开时消失

我读过在 React 中你不应该使用 querySelector 访问元素。但即使使用它我仍然无法让它工作。

我不想完全重构我将在下面添加的代码:

项目页面:

const Projects = () => {
  let cards = document.getElementsByClassName("list")
  const [Repos, setRepos] = useState([]);
  const Hider = (id) => {
    console.log(cards)
    // cards.classList.add('hidden')
  }
  useEffect(() => {
    axios.get("https://api.github.com/users/Leehamb99/repos").then((response) => {
      setRepos(response.data)


    })
      .catch(err => {
        console.log(err)
      })

  }, []);

  return (
    <>
      {Repos.map((repo, index) => {
        return (
          <div className="list" onClick={() => { Hider(index) }}>
            <ProjectCard key={index} name={repo.name} />
          </div>
        )
      })}
    </>
  )



};

项目卡组件:

const ProjectCard = (props) => {


  const [flip, setFlip] = useState(false);
  return (
    <ReactCardFlip isFlipped={flip}
      flipDirection="vertical">
      <div style={{
        display: 'flex',
        flexWrap: 'wrap',
        width: '75px',
        height: '75px',
        background: 'gray',
        fontSize: '18px',
        color: 'black',
        margin: '15px',
        borderRadius: '4px',
        textAlign: 'center',
        padding: '20px',
        boxShadow: '10px'
      }} onClick={() => setFlip(!flip)}>
        {props.name}
      </div>
      <div style={{
        width: '500px',
        height: '500px',
        background: '#F0EDE4',
        fontSize: '18px',
        color: 'black',
        margin: '15px',
        borderRadius: '4px',
        textAlign: 'center',
        padding: '20px',
        boxShadow: '10px'
      }} onClick={() => setFlip(!flip)}>
        Computer Science Portal.
      </div>
    </ReactCardFlip>
  );
}

(内联样式很快就会移动到 css,不用担心)所以我的方法是向该组件的所有实例添加一个名为“隐藏”(具有“显示:无”属性)的 class 除了我点击了一个。

由于我的前端知识非常有限,所以我可能会以错误的方式进行处理。

如果您正在为您的作品集做这方面的工作,那么遵循良好的代码标准就更加重要了。

您正在执行的内联样式绝对糟糕。 如果看到这样的代码,任何半正经的工程师都会扔掉你的简历。

将您的样式放在 css/scss/etc 中。 文件并将其导入到组件中。 或者有一个基本样式表并在其中完成所有操作。 或者使用样式化的组件。

或者绝对最低限度,提取样式变量,以便返回方法可读。 例如:

const style = { ... }

return <div style={style}/>

但我只对以组件属性/状态为条件的稀疏样式执行此操作。

我的偏好是将每个组件放在自己的文件夹中(在 components 文件夹中),并且在该文件夹中有 index.tsx 和 styles.scss,我们从 index.tsx 导出组件,该组件导入 styles.scss。

对于每个组件。 如果这是有道理的。 但是有很多可接受的方式。

此外,我会考虑切换到 TypeScript - 现在绝大多数商业项目都在他们的项目中使用它。

无论如何,就您遇到的问题而言:

你假设你永远不想使用查询选择器是正确的。 几乎没有 99.9% 的时间。

要轻松解决此问题,您可以做的是将逻辑移动到项目而不是 Card 组件中。

就像在项目中一样:

const [flippedCardIndex, setFlippedCardIndex] = useState(undefined);

然后将 onclick function 传递给 Card 组件(调用 setFlippedCardIndex(idx) ),以及另一个道具(例如 isFlipped),根据 flippedCardIndex 是否等于卡中的索引来判断是否翻转地图()。 您可以使用它来确定我们是否要显示:如果索引不等于 flippedCardIndex,则隐藏。

然后去掉Card中翻转的state变量。

可能是更好的方法,但这会奏效。

我已经为你简化了这个。 当点击卡片时只显示该卡片而不隐藏其他卡片:

import { ReactElement } from 'react';

import * as React from 'react';

const cards = Array.from({ length: 5 }).map((item, index) => ({
  title: `Item ${index}`,
}));

export default function App(): ReactElement {
  const [showingCard, showCard] = React.useState<number | null>(null);
  function toggleDisplayCard(index) {
    showCard((prev) => (prev === index ? null : index));
  }
  return (
    <div style={{ display: 'flex', gap: '0.5em' }}>
      {showingCard!==null ? (<Card
          isShown={true}
          title={cards[showingCard].title}
          onClick={() => toggleDisplayCard(showingCard)}
        />) : cards.map(({ title }, index: number) => (
        <Card
          title={title}
          onClick={() => toggleDisplayCard(index)}
        />
      ))}
    </div>
  );
}

function Card({
  title,
  onClick,
  isShown
}: {
  isShown?: boolean;
  title: string;
  onClick: any;
}): ReactElement {
  return (
    <div
      style={{
        cursor: 'pointer',
        border: isShown ? '2px solid yellowgreen' : '1px solid silver',
        display: 'flex',
        padding: '1rem',
      }}
      onClick={onClick}
    >
      {title}
    </div>
  );
}

您需要记住以防止在生产中以正确的方式使用 React.memo、React.useMemo、React.useCallback 浪费渲染。

也许这不是最有效的做事方式,因为我在每次点击卡片时调用迭代,但它似乎有效!

也只用了几行代码。 这是我的解决方案:

  const Hider = (id) => {
    click++
    for (let i = 0; i < cards.length; i++) {
      cards[i].classList.add("hidden")
    }
    cards[id].classList.remove("hidden")
    if (click % 2 == 0){
      for (let i = 0; i < cards.length; i++) {
        cards[i].classList.remove("hidden")
      }
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM