简体   繁体   English

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

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

I'm working on my portfolio as I'm a jobless junior currently and I'm finding it practically impossible to get all instances of a component to disappear upon the interaction (click) of another instance of said component.我正在处理我的投资组合,因为我目前是一名失业的初级人员,我发现几乎不可能让一个组件的所有实例在该组件的另一个实例的交互(单击)时消失。

I essentially have cards which were created with react-card-flip;我基本上有用 react-card-flip 创建的卡片; when the user clicks on one of these cards it will flip and expand in size to show more details.当用户点击其中一张卡片时,它会翻转并扩大尺寸以显示更多详细信息。 There are multiple instances of these cards which are created through an axios GET request to api.github... The part I have not managed to get working is making the rest of the cards disappear upon expansion of the clicked card这些卡片有多个实例是通过对 axios GET 请求 api.github 创建的...我没有设法开始工作的部分是使卡片的 rest 在单击的卡片展开时消失

I've read that in React you shouldn't be accessing elements using querySelector.. but even using that I can still not get it to work.我读过在 React 中你不应该使用 querySelector 访问元素。但即使使用它我仍然无法让它工作。

I would prefer not to completely refactor my code which I'll add below:我不想完全重构我将在下面添加的代码:

Projects Page:项目页面:

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>
        )
      })}
    </>
  )



};

ProjectCard Component:项目卡组件:

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>
  );
}

(inline styling will be moved to a css soon don't worry) So my approach to this would be to add a class called "hidden" (which has a "display: none" attribute) to all instances of this component apart from the one I have clicked. (内联样式很快就会移动到 css,不用担心)所以我的方法是向该组件的所有实例添加一个名为“隐藏”(具有“显示:无”属性)的 class 除了我点击了一个。

Perhaps I'm going about it the wrong way since my front-end knowledge is quite limited.由于我的前端知识非常有限,所以我可能会以错误的方式进行处理。

If you're working on this for your portfolio, then it is every bit more important that you're following good code standards.如果您正在为您的作品集做这方面的工作,那么遵循良好的代码标准就更加重要了。

In-line style as you're doing it is absolutely terrible.您正在执行的内联样式绝对糟糕。 Any half decent engineer will toss out your resume if they see code like that.如果看到这样的代码,任何半正经的工程师都会扔掉你的简历。

Put your styling in a css/scss/etc.将您的样式放在 css/scss/etc 中。 file and import it into the component.文件并将其导入到组件中。 Or have a base style sheet and do it all in there.或者有一个基本样式表并在其中完成所有操作。 Or use styled components.或者使用样式化的组件。

Or the absolute bare minimum, extract out style variables so the return method is readable.或者绝对最低限度,提取样式变量,以便返回方法可读。 eg:例如:

const style = { ... }

return <div style={style}/>

But I only do this for sparse styling that is conditional on component props/state.但我只对以组件属性/状态为条件的稀疏样式执行此操作。

My preference is to have each component in its own folder (in the components folder), and in that folder have index.tsx and styles.scss, where we export the component from index.tsx, and that component imports styles.scss.我的偏好是将每个组件放在自己的文件夹中(在 components 文件夹中),并且在该文件夹中有 index.tsx 和 styles.scss,我们从 index.tsx 导出组件,该组件导入 styles.scss。

For every component.对于每个组件。 If that makes sense.如果这是有道理的。 But there's lots of acceptable ways.但是有很多可接受的方式。

Also, I would consider switching to TypeScript - the strong majority of commercial projects nowadays are using it for their projects.此外,我会考虑切换到 TypeScript - 现在绝大多数商业项目都在他们的项目中使用它。

Anyway, in terms of the issue you have:无论如何,就您遇到的问题而言:

You're correct in assuming you never want to use query selectors.你假设你永远不想使用查询选择器是正确的。 Almost never 99.9% of the time.几乎没有 99.9% 的时间。

What you could do to solve this pretty easily is you could move the logic to Projects instead of in the Card component.要轻松解决此问题,您可以做的是将逻辑移动到项目而不是 Card 组件中。

so like in Projects:就像在项目中一样:

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

Then pass the an onclick function to the Card component, (which calls setFlippedCardIndex(idx) ), along with another prop (eg isFlipped) for if it is or isn't flipped based on whether flippedCardIndex is equal to the index of the card in the.map().然后将 onclick function 传递给 Card 组件(调用 setFlippedCardIndex(idx) ),以及另一个道具(例如 isFlipped),根据 flippedCardIndex 是否等于卡中的索引来判断是否翻转地图()。 Which you can use to determine if we want to display: hidden if the index does not equal the flippedCardIndex.您可以使用它来确定我们是否要显示:如果索引不等于 flippedCardIndex,则隐藏。

and then get rid of the flipped state variable in Card.然后去掉Card中翻转的state变量。

Might be a better way, but that will work.可能是更好的方法,但这会奏效。

I've simplified this for you.我已经为你简化了这个。 When clicks on a card just show that card without hiding others:当点击卡片时只显示该卡片而不隐藏其他卡片:

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>
  );
}

You need memorize to prevent wasted renders using React.memo, React.useMemo, React.useCallback in proper way in a production.您需要记住以防止在生产中以正确的方式使用 React.memo、React.useMemo、React.useCallback 浪费渲染。

Perhaps this isn't the most efficient way of doing things, since I'm calling an iteration on every click of a card, but it seems to work!也许这不是最有效的做事方式,因为我在每次点击卡片时调用迭代,但它似乎有效!

Only took a few lines of code too.也只用了几行代码。 Here was my solution:这是我的解决方案:

  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.

相关问题 我想在单击时更改 div 的显示 -React Styled Component - I wan to change display of a div when clicked -React Styled Component React hook useState 更新组件的所有实例 - React hook useState updating all instances of component 单击某个手风琴时如何关闭其他手风琴,还如何在隐藏父级时隐藏说明? - how do I close other accordions when one is clicked, Also How to hide description upon hiding the parent? 在React中单击组件时将类添加到同级中 - Add class to siblings when Component clicked in React 单击组件时如何更改仅通过.map() 渲染的一个反应组件的样式 - how to change the style of only one react component that is being render through .map() when the component is clicked 如何在 React 中隐藏组件的 div 内的滚动? - How to hide scroll inside div of a Component in React? 如何添加一个按钮,单击该按钮会在反应中转换我所有可编辑的文本字段? - How do I add a button that when clicked converts all my text field editable in react? 在另一个组件中导入此组件时,如何使用 className 修改按钮组件 - How do I modify a button component with className when I importing this component in another component 将样式导入到React组件中时,如何分配基于关闭状态进行更新的className? - When importing styles into a React component, how do I assign a className that updates based off state? 单击反应时将 div 中的组件移动到另一个 div - Move component in a div to another div when clicked in react
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM