React:需要有关基于单击按钮实现某些数组元素的建议

React: Need advice on implementing certain array elements based on a clicked button

我有一个 React 应用程序,我试图根据您单击的按钮呈现某些数组元素。为此,我使用了 React useState、一个名为 onHandleChange 的事件处理程序、一个 switch 方法、onClickonChange 和一些 map 函数来呈现我的组件。但是,如果我尝试实施 onClickonChange,我会收到以下错误

To many re-renders. React limits the amount of re-renders to prevent an infinite loop.

可以使用我的钩子和一些方法查看我的代码 here on codesandbox as well as below. I am currenlty using tailwindcss for styling. I am approaching the matter as discussed in 线程,但它使用 javascript。如果有人对他们将如何以不同的方式处理此问题有任何建议,我很高兴听到。

Portfolio.js

import React, { useState } from 'react'

const Portfolio = () => {
  const buttonList = ['All', 'App', 'Card', 'Logo', 'Web'];
  const imageList =
    [
      {
        name: 'App 1',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app1.jpg',
      },
      {
        name: 'Web 2',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web2.jpg',
      },
      {
        name: 'App 3',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app3.jpg',
      },
      {
        name: 'Card 1',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card1.jpg',
      },
      {
        name: 'Card 2',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card2.jpg',
      },
      {
        name: 'Web 3',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web3.jpg',
      },
      {
        name: 'Card 3',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card3.jpg',
      },
      {
        name: 'App 2',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app2.jpg',
      },
      {
        name: 'Logo 1',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo1.jpg',
      },
      {
        name: 'Logo 3',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo3.jpg',
      },
      {
        name: 'Web 1',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web1.jpg',
      },
      {
        name: 'Logo 2',
        image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo2.jpg',
      },
    ];

  const [fade, setFade] = useState(false);

  const handleOnChange = (param) => {
    if (setFade(!fade)) {
      switch (param) {
        case 'App':
          return (imageList[0] && imageList[2] && imageList[7]);
        case 'Card':
          return (imageList[3] && imageList[4] && imageList[6]);
        case 'Logo':
          return (imageList[8] && imageList[9] && imageList[11]);
        case 'Web':
          return (imageList[1] && imageList[5] && imageList[10]);
        default:
          return (imageList);
      }
    }
  }

  return (
    <div id="portfolio" className="py-20">
      <div className="container px-4 mx-auto">
        <div className="text-center">
          <h1 className="text-4xl font-semi-bold mt-6 mb-3">Our Previous Works</h1>
          <p className="text-md font-normal">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor <br></br> incididunt ut labore et dolore magna aliqua. </p>
          <hr className="border-b-2 border-red-700 my-10 inline-block" style={{ width: 100 }}></hr>
        </div>
      </div>
      <div className="container px-4 mx-auto">
        <div className="w-full">
          <ul id="portfolio-filters" className="mb-12 list-none flex justify-center flex-wrap">

            {/* onClick is included here in this tag WHERE onClick={setFade(!fade)}*/}

            {buttonList.map((item, index) => (
              <li data-filter=".filter-all .filter-app, .filter-card, .filter-logo, .filter-web" className="filter-active" key={index}>
                <button href="#All" className="btn btn-banner text-black uppercase bg-gray-200 text-md text-center flex mx-4 mb-2 px-6 py-2 border rounded hover:bg-red-600 hover:text-white focus:text-white focus:outline-none focus:bg-red-600 transition ease-in-out duration-300">{item}
                </button>
              </li>
            ))}
          </ul>
        </div>
      </div>
      <div className="container px-4 mx-auto">
        <div className="grid sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4">

          {/* onChange is included here in this div WHERE onChange={handleOnChange}*/}

          {imageList.map((item, index) => (
            <a href="/" key={index}>
              <div className='cursor-pointer relative overflow-hidden'>
                <img className='h-full w-full object-none object-left transition duration-700 ease-in-out transform hover:-translate-y-4' src={item.image} alt={item.name} />
                <div className='absolute pl-1 pt-2 leading-tight h-16 w-full bg-red-600 -bottom-20 transition duration-300 ease-in-out transform hover:-translate-y-4'>
                  <h4 className='text-white text-sm font-bold'>{item.name}</h4>
                  <span className='text-white text-xs font-normal'>Alored dono par</span>
                </div>
              </div>
            </a>
          ))}
        </div>
      </div>
    </div>
  )
}

export default Portfolio;

重新渲染限制错误:

我重新审视了这个问题并使用了不同的方法。

我决定将它们分成两个单独的文件,而不是将我的所有代码捆绑到一个地方,一个名为 Projects.js,另一个名为 Project.js.

我的 Project.js 包含我想列出的所有数据,Projects.js 包含我的主程序。我在 Project.js 中将所有数据提取为 const,以便我可以将它们作为道具传递给 Projects.js。然后我重写了我的主程序,这样每点击一个按钮,就会出现一个不同的元素数组。

Project.js

export const buttonList = ['All', 'App', 'Card', 'Logo', 'Web'];
export const imageList =
  [
    {
      name: 'App 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app1.jpg',
    },
    {
      name: 'Web 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web2.jpg',
    },
    {
      name: 'App 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app3.jpg',
    },
    {
      name: 'Card 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card1.jpg',
    },
    {
      name: 'Card 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card2.jpg',
    },
    {
      name: 'Web 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web3.jpg',
    },
    {
      name: 'Card 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card3.jpg',
    },
    {
      name: 'App 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app2.jpg',
    },
    {
      name: 'Logo 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo1.jpg',
    },
    {
      name: 'Logo 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo3.jpg',
    },
    {
      name: 'Web 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web1.jpg',
    },
    {
      name: 'Logo 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo2.jpg',
    },
  ];
export const appList =
  [
    {
      name: 'App 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app1.jpg',
    },
    {
      name: 'App 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app2.jpg',
    },
    {
      name: 'App 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/app3.jpg',
    },
  ];
export const cardList =
  [
    {
      name: 'Card 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card1.jpg',
    },
    {
      name: 'Card 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card2.jpg',
    },
    {
      name: 'Card 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/card3.jpg',
    },
  ];
export const logoList =
  [
    {
      name: 'Logo 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo1.jpg',
    },
    {
      name: 'Logo 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo2.jpg',
    },
    {
      name: 'Logo 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/logo3.jpg',
    },
  ];
export const webList =
  [
    {
      name: 'Web 1',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web1.jpg',
    },
    {
      name: 'Web 2',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web2.jpg',
    },
    {
      name: 'Web 3',
      image: 'https://bucket4origin.s3.us-east-2.amazonaws.com/web3.jpg',
    },
  ];

Project.js

import React, { useState } from 'react'
import { buttonList, imageList, appList, cardList, logoList, webList } from './subProjects/Project'
import { animated, useSpring } from 'react-spring'

const Projects = () => {
  const [isGrid, setIsGrid] = useState('')
  return (
    <div id="portfolio" className="py-20">
      <div className="container px-4 mx-auto">
        <div className="text-center">
          <h1 className="text-4xl font-semi-bold mt-6 mb-3">Our Previous Works</h1>
          <p className="text-md font-normal">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor <br></br> incididunt ut labore et dolore magna aliqua. </p>
          <hr className="border-b-2 border-red-700 my-10 inline-block" style={{ width: 100 }}></hr>
        </div>
      </div>
      <div className="container px-4 mx-auto">
        <div className="w-full mb-12 list-none flex justify-center flex-wrap">
{% --------------------------- UPDATED ------------------------------- %}
          {buttonList.map(item => (
            <button
              type="button"
              key={item}
              className="btn btn-banner text-black uppercase bg-gray-200 text-md text-center flex mx-4 mb-2 px-6 py-2 border rounded hover:bg-red-600 hover:text-white focus:text-white focus:outline-none focus:bg-red-600 transition ease-in-out duration-300"
              onClick={() => setIsGrid(item)}
            >
              {item}
            </button>
          ))}
{% --------------------------- UPDATED ------------------------------- %}
        </div>
      </div>
      <div className="container px-4 mx-auto">
        <div className="grid sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4">
{% --------------------------- UPDATED ------------------------------- %}
          {(isGrid === "All" || isGrid === "") && imageList.map((item, i) => (
            <WebImage key={i} src={item} />
          ))}
          {isGrid === "App" && appList.map((item, i) => (
            <WebImage key={i} src={item} />
          ))}
          {isGrid === "Card" && cardList.map((item, i) => (
            <WebImage key={i} src={item} />
          ))}
          {isGrid === "Logo" && logoList.map((item, i) => (
            <WebImage key={i} src={item} />
          ))}
          {isGrid === "Web" && webList.map((item, i) => (
            <WebImage key={i} src={item} />
          ))}
{% --------------------------- UPDATED ------------------------------- %}
        </div>
      </div>
    </div>
  )
};

{% --------------------------- NEW! ------------------------------- %}
const WebImage = ({ src }) => {
  const props = useSpring({ opacity: 1, from: { opacity: 0 } })
  return (
    <div className='cursor-pointer relative overflow-hidden'>
      <animated.img className="h-full w-full object-none object-left transition duration-700 ease-in-out transform hover:-translate-y-4" src={src.image} alt={src.name} style={{ ...props }} />
      <div className='absolute pl-1 pt-2 leading-tight h-16 w-full bg-red-600 -bottom-20 transition duration-300 ease-in-out transform hover:-translate-y-4'>
        <h4 className='text-white text-sm font-bold'>{src.name}</h4>
        <span className='text-white text-xs font-normal'>Alored dono par</span>
      </div>
    </div>
  )
}
{% --------------------------- NEW! ------------------------------- %}

export default Projects;