React не обновляет состояние при втором щелчке

#javascript #reactjs #onclick #react-hooks #state

#javascript #reactjs #onclick #реагирующие крючки #состояние

Вопрос:

Я создаю простое приложение react, в котором пользователи нажимают на определенную область на карте и получают карусель с изображениями продуктов из этой области. Проблема в том, что при первом щелчке состояние обновляется нормально, и продукты отображаются, но при каждом втором щелчке они этого не делают, третий щелчок работает нормально. Я пытался сначала очистить состояние при каждом новом щелчке, но это не работает. Я слышал, что это может быть связано с асинхронностью useState, но я не уверен, как заставить его работать в этом случае.

Компонент приложения с состоянием продуктов карусели:

 const App = () => {
  const [openCarousel, setOpenCarousel] = useState(false);
  const [carouselProducts, setCarouselProducts] = useState([]);

  const toggleCarousel = () => setOpenCarousel(!openCarousel);

  return (
    <Router>
      <Header />
      <Map open={toggleCarousel} setProducts={setCarouselProducts} />
      <main>
        <Container>
          <Route exact path="/" component={HomeScreen} />
          <Route exact path="/product/:id" component={ProductScreen} />
        </Container>
      </main>
      {openCarousel amp;amp; (
        <MultiCarousel
          products={carouselProd}
          close={toggleCarousel}
          setProducts={setCarouselProducts}
        />
      )}
      <Footer />
    </Router>
  );
};

export default App;
 

Компонент карты с 3 полями карты для щелчка. Функция clicked() должна очистить предыдущее состояние, вызвать setDisplayed(), чтобы установить новое состояние, а затем вызвать open(), чтобы открыть карусель.

 import React from "react";
import PropTypes from "prop-types";
import products from "../products.js";

const Map = ({ setProducts, open }) => {

  const setDisplayed = (e) => {
    let selectedProducts = [];
    let selectedProdSeries = "";
    let area = e.target.getAttribute("name");
    switch (area) {
     case "Podlachian":
        selectedProdSeries = "first";
        break;
      case "Lublin":
        selectedProdSeries = "second";
        break;
      case "Subcarpathian":
        selectedProdSeries = "third";
        break;
      default:
        selectedProdSeries = "";
    }

    let selectedSeries = products.filter(
      (product) => product.series === selectedProdSeries
    );
    selectedProducts = selectedSeries;
    setProducts(selectedProducts);

    console.log(selectedProdSeries);
  };

  const clicked = (e) => {
     setProducts([]);
    setDisplayed(e);
    open();
  };

  return (
    <>
      <div className="main-map-container">
        <div className="mapdiv">
          <div className="svg-div">
            <svg
              baseProfile="tiny"
              fill="#7c7c7c"
              stroke="#ffffff"
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth="2"
              version="1.2"
              viewBox="0 0 1000 948"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M902.7 429.6l-0.8 0.5-1.8"
                id="POL3150"
                name="Podlachian"
                onClick={(e) => {
                  clicked(e);
                }}
              ></path>
              <path
                d="M902.7 429.6l0.7 0.6 1.1 1.6 0.3 2.1-0.8 2.9 2.3 1.5 7.1 1.9 "
                id="POL3151"
                name="Lublin"
                onClick={(e) => {
                  clicked(e);
                }}
              ></path>
              <path
                d="M950.7 741.8l-1.4 2.2-7.9 "
                id="POL3152"
                name="Subcarpathian"
                onClick={(e) => {
                  clicked(e);
                }}
              ></path>
            
              <circle cx="117.2" cy="233.1" id="0"></circle>
              <circle cx="611.2" cy="696.4" id="1"></circle>
              <circle cx="678" cy="712.1" id="2"></circle>
            </svg>
          </div>
        </div>
      </div>
    </>
  );
};

Map.propTypes = {
  open: PropTypes.func.isRequired,
  setProducts: PropTypes.func.isRequired,
};

export default Map;
 

Комментарии:

1. Вы используете переключатель для состояния openCarousel. Если пользователь нажимает на элемент на карте, для карусели openCarousel сначала будет установлено значение true, но при втором нажатии на карту оно будет переключено на false.

2. MultiCarousel должно отображаться только при наличии данных. То, что вы делаете, это рассматриваете его как кнопку для включения и выключения с использованием логических значений в состоянии openCarousel .

3. @shilch Да, очевидно, что так оно и было, большое вам спасибо. Я чувствую себя таким тупым прямо сейчас.