javascript 如何确保React更新是有序的?

enyaitl3  于 2023-04-28  发布在  Java
关注(0)|答案(1)|浏览(107)

我正在构建一个多选下拉列表,并希望在用户选择一个选项时隐藏选项,但我无法在selectedCategoriesData状态更新后隐藏下拉列表,因为setShowCategories(false);更新会停止selectedCategoriesData状态更新。
如何确保先更新selectedCategoriesData状态,然后再更新setShowCategories

  • 请阅读我的问题评论 *

以下是文件:

Filter.jsx

import classes from "./Filter.module.css";

const Filter = ({ categories }) => {
  const [selectedCategoriesData, setSelectedCategoriesData] = useState([]);
  const [showCategories, setShowCategories] = useState(false);
  const handleCategoryInput = (e) => {};

  const handleCategorySelect = (categoryChosen) => {
    setSelectedCategoriesData([...selectedCategoriesData, categoryChosen]);
    // setShowCategories(false);   <---- This is causing not to update the selectedCategoriesData state, why ? I also want to hide the dropdown of options, so I need to set setShowCategories to false AFTER the selectedCategoriesData state is updated.
  };

  return (
    <div className={classes.filter_container}>
      <div className="category_filter">
        <label htmlFor="ctgry">Category</label>
        <input
          className={classes.category_select}
          onChange={handleCategoryInput}
          onFocus={() => setShowCategories(true)}
          onBlur={() => setShowCategories(false)}
        ></input>
        {showCategories && (
          <ul className={classes.categories_data}>
            {categories.map((category, index) => (
              <li tabIndex={0} key={index} onClick={() => handleCategorySelect(category)}>
                <span>{category}</span>
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  );
};

export default Filter;

Filter.module.css

.filter_container {
  margin-left: 100px;
}

.filter_container label {
  font-size: 1.6rem;
  font-weight: 600;
}

.category_select {
  min-width: 20rem;
  border: 1px solid #494949;
  padding: 1rem;
  font-size: 1.4rem;
  display: block;
}

.categories_data {
  border: 1px solid gray;
  border-top: none;
  font-size: 1.4rem;
  max-height: 20rem;
  width: 20rem;
  overflow-x: hidden;
  overflow-y: hidden;
}

.categories_data:hover {
  overflow-y: scroll;
  overflow-x: hidden;
}

.categories_data li span {
  display: inline-block;
  padding: 0.65rem 0.8rem;
}

.categories_data li:hover {
  background-color: #e2e2e2;
  cursor: pointer;
}

.categories_data::-webkit-scrollbar {
  width: 1rem; /* width of the entire scrollbar */
}

.categories_data::-webkit-scrollbar-track {
  background: transparent; /* color of the tracking area */
}

.categories_data::-webkit-scrollbar-thumb {
  background-color: #4b4b4b; /* color of the scroll thumb */
  border-radius: 20px; /* roundness of the scroll thumb */
  border: 3px solid #fff;
  /* creates padding around scroll thumb */
}

类别 prop 是['category-1', 'category-2', 'category-3', 'category-4', 'category-5', 'category-6']数组

niwlg2el

niwlg2el1#

在仔细阅读了您的问题并运行了您的代码之后,我意识到该问题是由于输入语句中的onBlur={() => setShowCategories(false)}功能引起的。这是在更新SelectedCategoriesData状态之前触发setShowCategories(false)
要获得在输入组件外部单击时关闭下拉菜单的功能,可以使用refeventlistener而不是onBlur。下面是这个实现的代码:

const Filter = ({ categories }) => {
  const [selectedCategoriesData, setSelectedCategoriesData] = useState([]);
  const [showCategories, setShowCategories] = useState(false);
  const handleCategoryInput = (e) => {};

  const handleCategorySelect = (categoryChosen) => {
    console.log(categoryChosen);

    setSelectedCategoriesData([...selectedCategoriesData, categoryChosen]);
    setShowCategories(false); //<---- This is causing not to update the selectedCategoriesData state, why ? I also want to hide the dropdown of options, so I need to set setShowCategories to false AFTER the selectedCategoriesData state is updated.
  };

  // This will reference to the div surrounding your input components
  const ref = useRef();

  // Here we listen for mousdown event and if its outside our ref component we will make dropdown open false
  useEffect(() => {
    const handleClickOutside = (event) => {
      if (!ref.current.contains(event.target)) {
        setShowCategories(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
  }, [ref]);

  return (
    <div className="filter_container">
      <div className="category_filter">
        <label htmlFor="ctgry">Category</label>
        <h4>selectedCategoriesData: {selectedCategoriesData}</h4>
        {showCategories ? <h1>True</h1> : <h1>False</h1>}
        {/* Input Component Start */}
        <div ref={ref}>
          <input
            className="category_select"
            onChange={handleCategoryInput}
            onFocus={() => setShowCategories(true)}
          ></input>
          {showCategories && (
            <ul className="categories_data">
              {categories.map((category, index) => (
                <li
                  tabIndex={0}
                  key={index}
                  onClick={() => handleCategorySelect(category)}
                >
                  <span>{category}</span>
                </li>
              ))}
            </ul>
          )}
          </div>
          {/* Input Component End */}
      </div>
    </div>
  );
};

export default Filter;

我希望这个答案对你有帮助。以下是sandbox链接:Sandbox Link

相关问题