React:如何只更新一个元素的状态,而不是批量更新

React: How to update state for just one element, rather than batch update

我是 React 的初学者。我有一个项目正在处理一些样本旅游。我想使用“阅读 more/show less”功能来描述每次游览。阅读 more/show less 按钮正在切换,但当我希望它只切换点击的游览时,它会在单击时显示所有游览的更多或更少的描述。换句话说,它正在更新所有游览的状态,而不仅仅是被点击的游览。希望这是有道理的。请帮忙!提前致谢。

import React, { useState, useEffect } from 'react';
import './index.css';

const url = 'https://course-api.com/react-tours-project';

const Tour = () => {
    const [tourItem, setTourItem] = useState('');

    const removeItem = (id) => {
        let newList = tourItems.filter((item) => item.id !== id);
        setTourItem(newList);
    };
    const [fetchingData, setFetchingData] = useState(true);

    useEffect(() => {
        const abortController = new AbortController();
        const fetchUrl = async () => {
            try {
                const response = await fetch(url, {
                    signal: abortController.signal,
                });
                if (fetchingData) {
                    const data = await response.json();
                    setTourItem(data);
                }
                setFetchingData(false);
            } catch (e) {
                console.log(e);
            }
        };
        fetchUrl();
        return () => {
            //cleanup!
            abortController.abort();
        };
    });

    const tourItems = Object.values(tourItem);

    const [readMore, setReadMore] = useState(false);

    return (
        <>
            {tourItems.map((item) => {
                return (
                    <div key={item.id}>
                        <article className='single-tour'>
                            <img src={item.image} alt={item.name} />
                            <footer>
                                <div className='tour-info'>
                                    <h4>{item.name}</h4>
                                    <h4 className='tour-price'>
                                        ${item.price}
                                    </h4>
                                </div>
                                {readMore ? (
                                    <p>
                                        {item.info}
                                        <button
                                            onClick={() => setReadMore(false)}
                                        >
                                            Show Less
                                        </button>
                                    </p>
                                ) : (
                                    <p>
                                        {item.info.slice(0, 450) + '...'}
                                        <button
                                            onClick={() => setReadMore(true)}
                                        >
                                            Read More
                                        </button>
                                    </p>
                                )}
                                <button
                                    className='delete-btn'
                                    onClick={() => removeItem(item.id)}
                                >
                                    Not Interested
                                </button>
                            </footer>
                        </article>
                    </div>
                );
            })}
        </>
    );
};

export default Tour;

好问题!这是因为您与所有游览项目共享 readMore 状态。您可以通过将旅游项目封装到组件中来解决此问题。

它应该看起来像这样;

封装各个旅游项目的组件

import React, {useState} from "react";
import "./index.css";

const SpecificTourItems = ({item, removeItem}) => {
    const [readMore, setReadMore] = useState(false);
    return (
      <div key={item.id}>
        <article className="single-tour">
          <img src={item.image} alt={item.name} />
          <footer>
            <div className="tour-info">
              <h4>{item.name}</h4>
              <h4 className="tour-price">${item.price}</h4>
            </div>
            {readMore ? (
              <p>
                {item.info}
                <button onClick={() => setReadMore(false)}>Show Less</button>
              </p>
            ) : (
              <p>
                {item.info.slice(0, 450) + "..."}
                <button onClick={() => setReadMore(true)}>Read More</button>
              </p>
            )}
            <button className="delete-btn" onClick={() => removeItem(item.id)}>
              Not Interested
            </button>
          </footer>
        </article>
      </div>
    );
  };

  export default SpecificTourItems;

获取并映射所有游览项目的组件(您的旧组件:))

import React, {useState, useEffect} from "react";
import SpecificTourItems from "./SpecificTourItems";

const url = "https://course-api.com/react-tours-project";

const Tour = () => {
  const [tourItem, setTourItem] = useState("");

  const removeItem = (id) => {
    let newList = tourItems.filter((item) => item.id !== id);
    setTourItem(newList);
  };
  const [fetchingData, setFetchingData] = useState(true);

  useEffect(() => {
    const abortController = new AbortController();
    const fetchUrl = async () => {
      try {
        const response = await fetch(url, {
          signal: abortController.signal,
        });
        if (fetchingData) {
          const data = await response.json();
          setTourItem(data);
        }
        setFetchingData(false);
      } catch (e) {
        console.log(e);
      }
    };
    fetchUrl();
    return () => {
      //cleanup!
      abortController.abort();
    };
  });

  const tourItems = Object.values(tourItem);

  const [readMore, setReadMore] = useState(false);

  return (
    <>
      {tourItems.map((item, key) => {
        return (
          <SpecificTourItems item={item} removeItem={removeItem} key={key} />
        );
      })}
    </>
  );
};

export default Tour;

希望对您有所帮助,这是我第一次在 Stack Overflow 中回答问题。谢谢,祝你好运!