如何让切换开关显示/隐藏数组对象?

问题描述 投票:0回答:1

我试图在切换开关时显示/隐藏描述。我还想首先检查一下开关。当选中该开关时,应显示每个结果的描述。每个结果都有自己的描述。

我的代码没有做任何事情。相反,每个结果都会显示所有描述。切换开关不显示描述,但隐藏了它们。

// imports

const results = [...]

const upvoteSVG = '...';

const downvoteSVG = '...';

export default function SearchResults() {
    const [page, setPage] = useState(0); 
    const [description, setDescription] = useState(Array.isArray(results) ? results.map(result => result.description) : []);

    const List = () => {
        return (
            <>
            {
                results.slice(page * 10, page * 10 + 10).map((result) => {
                    return (
                        <div className="bg-gray-800 shadow-lg shadow-red-500 m-5">
                            <div className="flex flex-row gap-4 p-5">
                                <div className="flex flex-col w-1/2">
                                    <div className="flex flex-row gap-4">
                                        <p className="text-lg font-bold">{result.name}</p>
                                        <p className="text-blue-500"><Link href={result.url}>Website</Link></p>
                                    </div>
                                    <p>{result.categories.slice(0, 3).join(", ")}</p>
                                </div>
                                <div className="flex flex-row flex-wrap w-1/2">
                                    <p>{description}</p>
                                </div>
                            </div>
                            <div className="flex flex-row bottom-0 gap-4 bg-gray-900 justify-items-end justify-end pr-2">
                                <p>{result.upvotes}<button className="rounded-full bg-red-500 w-fit h-fit p-2 m-2"><Image src="upvote.svg" alt="upvote" width={20} height={20}/></button></p>
                                <p>{result.downvotes} <button className="rounded-full bg-red-500 w-fit h-fit p-2 m-2"><Image src="downvote.svg" alt="downvote" width={20} height={20}/></button></p>
                            </div>
                        </div>
                    )
                })
            }
            </>
        )
    }

    const prevPage = () => {...}

    const nextPage = () => {...}

    const showDescription = () => {
        description ? setDescription([]) : setDescription(results.map(result => result.description));
    }

    const PaginationNumbers = () => {...}

    const NOP = () => {...}

    return (
        <div className="flex flex-col justify-center items-center">
            <div>
                <Search/>
            </div>
            <div className="flex flex-row justify-center items-center">
                <div className="w-1/2">
                    <List/>
                </div>
                <div className="w-1/2 m-2 p-2 flex flex-col justify-center items-center bg-gray-800">
                    <label className="inline-flex items-center cursor-pointer">
                        <input type="checkbox" value="" className="sr-only peer" id="toggle" onChange={showDescription}/>
                        <span className="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300 m-2">Show Description</span>
                        <div className="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-red-500 dark:peer-focus:ring-red-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-red-600" ></div> 
                    </label>
                </div>
            </div>
            <div className="flex flex-row justify-center items-center flex-wrap w-1/2">
                <button onClick={prevPage} className="bg-gray-800 text-white m-2 p-2 hover:bg-white hover:text-black rounded-lg">Prev</button>
                <PaginationNumbers/>
                <button onClick={nextPage} className="bg-gray-800 text-white m-2 p-2 hover:bg-white hover:text-black rounded-lg">Next</button>
            </div>
        </div>
    )
}

javascript reactjs next.js tailwind-css
1个回答
0
投票

考虑转换:

const [description, setDescription] = useState(Array.isArray(results) ? results.map(result => result.description) : []);

对于布尔标志,例如:

const [showDescriptions, setShowDescription] = useState(false);

这简化了状态,并且依赖性更少。

然后,使用

showDescriptions
中的这个
List
来有条件地显示描述:

{showDescriptions && (
  <div className="flex flex-row flex-wrap w-1/2">
    <p>{result.description}</p>
  </div>
)}

更新

showDescription()
以匹配此新格式:

const showDescription = () => setShowDescription(value => !value);

const { useState } = React;

const Search = () => 'Search';
const Link = (...props) => <a {...props}/>;
const Image = (...props) => <img {...props}/>;

const results = [
  {
    name: 'Foo',
    url: '',
    categories: ['Foo', 'Bar'],
    description: 'Foo description',
    upvotes: 5,
    downvotes: 5,
  },
  {
    name: 'Bar',
    url: '',
    categories: ['Foo', 'Bar'],
    description: 'Foo description',
    upvotes: 5,
    downvotes: 5,
  },
  {
    name: 'Baz',
    url: '',
    categories: ['Foo', 'Bar'],
    description: 'Foo description',
    upvotes: 5,
    downvotes: 5,
  }
];

const upvoteSVG = '...';

const downvoteSVG = '...';

function SearchResults() {
  const [page, setPage] = useState(0);
  const [showDescriptions, setShowDescription] = useState(false);

  const List = () => {
    return (
      <React.Fragment>
        {results.slice(page * 10, page * 10 + 10).map((result) => {
          return (
            <div className="bg-gray-800 shadow-lg shadow-red-500 m-5">
              <div className="flex flex-row gap-4 p-5">
                <div className="flex flex-col w-1/2">
                  <div className="flex flex-row gap-4">
                    <p className="text-lg font-bold">{result.name}</p>
                    <p className="text-blue-500">
                      <Link href={result.url}>Website</Link>
                    </p>
                  </div>
                  <p>{result.categories.slice(0, 3).join(', ')}</p>
                </div>
                {showDescriptions && (
                  <div className="flex flex-row flex-wrap w-1/2">
                    <p>{result.description}</p>
                  </div>
                )}
              </div>
              <div className="flex flex-row bottom-0 gap-4 bg-gray-900 justify-items-end justify-end pr-2">
                <p>
                  {result.upvotes}
                  <button className="rounded-full bg-red-500 w-fit h-fit p-2 m-2">
                    <Image
                      src="upvote.svg"
                      alt="upvote"
                      width={20}
                      height={20}
                    />
                  </button>
                </p>
                <p>
                  {result.downvotes}{' '}
                  <button className="rounded-full bg-red-500 w-fit h-fit p-2 m-2">
                    <Image
                      src="downvote.svg"
                      alt="downvote"
                      width={20}
                      height={20}
                    />
                  </button>
                </p>
              </div>
            </div>
          );
        })}
      </React.Fragment>
    );
  };

  const prevPage = () => {};

  const nextPage = () => {};

  const showDescription = () => setShowDescription(value => !value);

  const PaginationNumbers = () => {};

  const NOP = () => {};

  return (
    <div className="flex flex-col justify-center items-center">
      <div>
        <Search />
      </div>
      <div className="flex flex-row justify-center items-center">
        <div className="w-1/2">
          <List />
        </div>
        <div className="w-1/2 m-2 p-2 flex flex-col justify-center items-center bg-gray-800">
          <label className="inline-flex items-center cursor-pointer">
            <input
              type="checkbox"
              value=""
              className="sr-only peer"
              id="toggle"
              onChange={showDescription}
            />
            <span className="ms-3 text-sm font-medium text-gray-900 dark:text-gray-300 m-2">
              Show Description
            </span>
            <div className="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-red-500 dark:peer-focus:ring-red-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-red-600"></div>
          </label>
        </div>
      </div>
      <div className="flex flex-row justify-center items-center flex-wrap w-1/2">
        <button
          onClick={prevPage}
          className="bg-gray-800 text-white m-2 p-2 hover:bg-white hover:text-black rounded-lg"
        >
          Prev
        </button>
        <PaginationNumbers />
        <button
          onClick={nextPage}
          className="bg-gray-800 text-white m-2 p-2 hover:bg-white hover:text-black rounded-lg"
        >
          Next
        </button>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<SearchResults />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.tailwindcss.com/3.4.3"></script>

<div id="app"></div>

© www.soinside.com 2019 - 2024. All rights reserved.