【问题标题】:React toggle button after mapping through list通过列表映射后反应切换按钮
【发布时间】:2020-10-17 07:51:23
【问题描述】:

从对 Google 图书的 api 调用获得结果后,我想隐藏描述段落并使用隐藏的 css 类(顺风 css)有一个切换按钮。我目前只是控制台。在“查看描述”按钮上记录元素&我只是不确定如何在使用我的 toggleDesc() 函数循环通过 nodeList 后定位单个元素

React SearchBar 组件

import React, { useState, useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import axios from 'axios';

import { faSearch } from '@fortawesome/free-solid-svg-icons';

import SearchResult from '../search-result/search-result.component';

const SearchBar = () => {
  const [searchTerm, setSearchTerm] = useState('');
  const [books, setBooks] = useState({ items: [] });
  
  useEffect(() => {
      async function fetchBooks() {
          const newRes = await fetch(`${API_URL}?q=${searchTerm}`);
          const json = await newRes.json();
          const setVis = Object.keys(json).map(item => ({
              ...item, isDescVisible: 'false'
          }))
          setBooks(setVis);
      }
      fetchBooks();
  }, []);

  const toggleDesc = (id) => {
    const newBooks = books.items.map(book => book.id === id ? {...book, isDescVisible: !book.isDescVisible} : book);
    console.log(newBooks);
    setBooks(newBooks);
}

  const onInputChange = (e) => {
    setSearchTerm(e.target.value);
  };

  let API_URL = `https://www.googleapis.com/books/v1/volumes`;

  const fetchBooks = async () => {
    // Ajax call to API via axios
    const result = await axios.get(`${API_URL}?q=${searchTerm}`);

    setBooks(result.data);
    
  };

  // Handle submit
  const onSubmitHandler = (e) => {
    // prevent browser from refreshing
    e.preventDefault();
    // call fetch books async function
    fetchBooks();
  };

  // Handle enter press
  const handleKeyPress = (e) => {
      if (e.key === 'Enter') {
          e.preventDefault();

          fetchBooks();

      }
  }


  return (
    <div className="search-bar p-8">
      <div className="bg-white flex items-center rounded-full shadow-xl">
        <input
          className="rounded-l-full w-full py-4 px-6 text-gray-700 leading-tight focus:outline-none"
          id="search"
          type="text"
          placeholder="Try 'The Hunt For Red October by Tom Clancy' "
          onChange={onInputChange}
          value={searchTerm}
          onKeyPress={handleKeyPress}
        />
        <div className="p-4">
          <button
            onClick={onSubmitHandler}
            className="bg-blue-800 text-white rounded-full p-2 hover:bg-blue-600 focus:outline-none w-12 h-12 flex items-center justify-center"
          >
            <FontAwesomeIcon icon={faSearch} />
          </button>
        </div>
      </div>
      <div className='result mt-8'>
      <ul>
         <SearchResult books={books} toggleDesc={toggleDesc} />
      </ul>
      </div>
    </div>
  );
};

export default SearchBar;

搜索结果组件

import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';

import './search-result.styles.scss';

const SearchResult = ({ books, toggleDesc }) => {

  return (
    <div className="search-result mb-6">
      {books.items !== undefined &&
        books.items !== null &&
        books.items.map((book, index) => {
          return (
            <div key={index} className="book-info mb-2">
              <li className="ml-4">
                <div className="flex">
                  <LazyLoadImage
                    className="book-img px-4 py-2"
                    effect="blur"
                    alt={`${book.volumeInfo.title} book`}
                    src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`}
                  />
                  <div className="flex-1">
                    <h3 className="text-2xl">{book.volumeInfo.title}</h3>
                    <div>
                      <p className="flex">
                        <button
                          onClick={() => toggleDesc(book.id)}
                          className="bg-blue-800 mt-2 text-gray-200 rounded hover:bg-blue-400 px-4 py-3 text-sm focus:outline-none"
                          type="button"
                        >
                          View Description
                        </button>
                      </p>
                      {book.isDescVisible &&
                           <div
                           className="block border px-4 py-3 my-2 text-gray-700 desc-content"
                         >
                           <p>{book.volumeInfo.description}</p>
                         </div>
                      }
                    </div>
                    <h3 className="text-xl text-blue-800 mt-2 p-2">
                      Average time to read:{' '}
                    </h3>
                  </div>
                </div>
                <hr />
              </li>
            </div>
          );
        })}
    </div>
  );
};

export default SearchResult;

控制台

【问题讨论】:

    标签: javascript reactjs loops dictionary


    【解决方案1】:

    您必须为书籍的每个项目添加一个属性来处理描述可见性并在您单击按钮时更改它,这是一个基本示例

    useEffect(()=> {
      fetch(url).then(res => {
        const newRes = res.map(item=> ({ ...item, isDescVisible: 'false' })) // <— add the new property to all items set to false
        setBooks(newRes);
      })
    })
    
    <p className='flex'>
      <button
         onClick={() => toggleDesc(book.id)} // <—- pass the id or the whole book
         className='bg-blue-800 mt-2 text-gray-200 rounded hover:bg-blue-400 px-4 py-3 text-sm focus:outline-none'
         type='button'
      >
        View Description
      </button>
    </p>
    
    //here show the desc according to the value of the property you added, no need for the hidden class
    {book.isDescVisible && <div className='block border px-4 py-3 my-2 text-gray-700 desc-content'>
      <p>{book.volumeInfo.description}</p>
    </div>}
    

    这个函数需要在你设置状态的父节点上

    const toggleDesc = (id) => {
      const newBooks = books.map(book => book.id === id ? {...book, isDescVisible: !book.isDescVisible} : book); <-- toggle the property
      setBooks(newBooks); <—- save it in the state again
    };
    

    【讨论】:

    • 感谢您的回答。我可以使用 useEffect 钩子 useEffect(() =&gt; { async function fetchBooks() { const newRes = await fetch(${API_URL}?q=${searchTerm}); const json = await newRes.json(); const setVis = Object.keys(json).map(item =&gt; ({ ...item, isDescVisible: 'false' })) setBooks(setVis); } fetchBooks(); }, []); 更改属性,但单击其中一个视图描述按钮时,它似乎仍然针对数组中的所有书籍跨度>
    • 你改变了你的toggleDesc函数吗?
    • 是的,它在父级上,我看到当我单击它时确实会正确更改属性,但记录 newBooks 它会显示所有属性。 dom 更改为不显示任何书籍。 const toggleDesc = (id) =&gt; { const newBooks = books.items.map(book =&gt; book.id === id ? {...book, isDescVisible: !book.isDescVisible} : book); console.log(newBooks); setBooks(newBooks); }
    • 是的,console.log 可以打印所有书籍,您正在做的是将所有阵列替换为新的阵列,并使用您希望显示的 desc 更改的书籍,该控制台是否.log 显示您想要更改 isDescVisible 的书?
    • 我现在看到了问题,您的书籍状态是一个内部带有数组的对象,这应该可以解决问题setBooks({items: newBooks});
    猜你喜欢
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2023-02-23
    • 2022-09-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多