【问题标题】:State set on second click instead of first在第二次点击而不是第一次点击时设置状态
【发布时间】:2021-08-11 16:43:42
【问题描述】:

我有一个问题,我的状态仅在第二次点击时设置。我一直在阅读有关提升我试图实现的状态的信息,但我仍然遇到与此按钮相同的问题。状态传递有多个组件,也许这就是我可以使用一些帮助了解如何解决此问题的问题我会尝试以最简单的方式概述:

我有我的父表组件:

const TableView = ({...all the props}) => {

 const [sort, setSortBy] = useState({
    sortBy: "",
    order: "",
  });

  const handleOnsortChange = (values) => {
    setSortBy(values);
    trimData(items.sort(sorter), pageNumber, 50);
  };

// sort function
const sorter = (a, b) => { ...}

return (

<Table>
      <TableHeader handleOnsortChange={handleOnsortChange} sort={sort} />
...
)

表头组件:

const TableHeader = ({ handleOnsortChange, sort }) => {
  const onSortChange = (value) => {
    handleOnsortChange(value);
  };
  return (
    <thead className="payroll-list-header">
      <tr>
        <th>
          <span>Name</span> <SortView onChange={onSortChange} type={"fullName"} sort={sort} />
          <div className="arrow"></div>
        </th> ...
)

分拣机组件:

const SortView = ({ onChange, type, sort: { sortBy, order } }) => {
  const onClick = (order) => {
    onChange({ sortBy: type, order });
  };
  return (
    <div className="sort">
      <div onClick={() => onClick("asc")} className="icon-up">
        <Octicon
          icon={TriangleUp}
          className={`${order === "asc" && sortBy == type ? "active" : ""}`}
        ></Octicon>
      </div>
      <div onClick={() => onClick("desc")} className="icon-down">
        <Octicon
          icon={TriangleDown}
          className={`${order === "desc" && sortBy == type ? "active" : ""}`}
        ></Octicon>
      </div>
    </div>
  );
};

更新: TrimData & sorter 函数:在这些函数之外,sort 的状态会更新,但在我控制台 sort 内部时它是空的。

//sort providers
  const sorter = (a, b) => {
    const nameA = a.FullName.toUpperCase();
    const nameB = b.FullName.toUpperCase();

    let compare = 0;
    if (sort.sortBy === "fullName") {
      if (nameA > nameB) {
        compare = 1;
      } else if (nameA < nameB) {
        compare = -1;
      }
if (sort.order === "asc") {
      return compare;
    } else if (sort.order === "desc") {
      return compare * -1;
    }
  };

const trimData = (items, pageNumber, rows) => {
    const pages = items.length > 0 ? Math.ceil(items.length / rows) : 1;
    const trimStart = (pageNumber - 1) * rows;
    const trimEnd = trimStart + rows;
    const trimedData = items.slice(trimStart, trimEnd);

    setEndRange(trimEnd);
    setTrimedData(trimedData);
    setNumberOfPages(pages);
  };

您可以看到sort 被传递到排序组件并在父组件中设置。我试过在后代组件中设置它,但这没有帮助。也通过setSortBy 提供了相同的结果。我希望这不是一个大代码块,有人可以向初级开发人员提供建议:)

【问题讨论】:

  • 你确定状态保持不变,不是排序本身没有发生吗?这可能是因为初始排序已经是您尝试将其更改为的。
  • 排序的哪一部分不起作用?您提供的代码仅显示排序表“标题”。 “标题” (Octicon) 是否显示正确的 ordersortBy 值?如果是这样,则 sort 值的状态设置正确。实际排序本身不起作用吗?如果是这样,请提供有关 trimData 正在做什么以及 items 是什么的详细信息。我之所以问,是因为在我看来,一切都在以一种应该正确更新的方式传递下去。
  • 进一步调查后,我意识到状态正在设置,但由于某种原因,更新后的状态没有反映在我的辅助函数中。即trimDatasorter。我会将它们添加到问题中

标签: javascript reactjs react-hooks state


【解决方案1】:

排序仅在第二次单击时起作用的原因是,在第一次单击时,sort 值更新,trimData 函数使用的 sort 是单击之前的旧 sort 对象.

让我们考虑一下,sorter 是一个函数,它的 sort 对象在第一次渲染时设置为 {order: "", sortBy: ""}。当您单击一个按钮时,这是您的sorter 函数在您的items.sort 上使用的sort 对象。在setSortBy 中更新sort 然后将使用新值更新组件,并且组件将重新呈现。当组件重新渲染时,sorter 函数正在使用刚刚设置的sort,比如说{order: "asc", sortBy: "fullName"}(但该函数尚未被调用)。当您再次单击时,假设现在在 desc 上,然后使用用于渲染组件sort 对象调用该函数,即 {order: "asc", sortBy: "fullName"} 一个,而不是排序对象你传递的更新状态{order: "desc", sortBy: "fullName"}

尽量不要太混乱,因为您可以采用多种方法,最直接的选择是使用您想要更新状态的排序值创建“排序器”函数,然后再将其传递到 @987654339 @:

const handleOnsortChange = (values) => {
  // `values` is what you want the next `sort` value to be.
  setSortBy(values); 
  // but `sort` wont be updated yet, so just use `values` instead. 
  const sorterWithCorrectSort = (a, b) => {
    const nameA = a.FullName.toUpperCase();
    const nameB = b.FullName.toUpperCase();

    let compare = 0;
    if (values.sortBy === "fullName") { // "sort" renamed to "values"
      if (nameA > nameB) {
        compare = 1;
      } else if (nameA < nameB) {
        compare = -1;
      }
    if (values.order === "asc") {  // "sort" renamed to "values"
      return compare;
    } else if (values.order === "desc") {  // "sort" renamed to "values"
      return compare * -1;
    }
  };

  trimData(items.sort(sorterWithCorrectSortValues), pageNumber, 50);
}

有更好的方法来格式化代码,但我相信这是问题的核心。 sorter 函数中的 sort 对象是用于渲染组件的对象,而不是用于更新状态的对象。

【讨论】:

  • 哇,感谢您解释这一点并提供解决方案。这对我有用,我没想过将排序器功能放在句柄排序中。非常感谢!
  • @CourtneyJ 没问题!
猜你喜欢
  • 1970-01-01
  • 2017-07-03
  • 2014-11-09
  • 2021-11-03
  • 2021-10-28
  • 1970-01-01
  • 2021-11-23
  • 2016-07-14
  • 2014-06-04
相关资源
最近更新 更多