【问题标题】:How to use the value of `useSelector()` in click event handlers?如何在点击事件处理程序中使用 `useSelector()` 的值?
【发布时间】:2021-11-23 21:31:12
【问题描述】:

Foll 是代码的大纲。我的“cartSize”已经过时了。

function CartComp(props) {
  const [cartSize, setCartSize] = useState(0);

const cartList = useSelector((state) => state.cart.cartItems);

useEffect(() => {
  setCartSize(() => {
    return cartList.length;
  });
}, [cartList]);

const onClickAddBtn = (cartObj) => {
  if (cartSize > 4) { // outdated state
    alert(`cannot add more than ${cartSize} items`);
  }
}
<button
onClick={onClickAddBtn.bind(this, cartObj)}
>
Add
</button>
}

基本上,在点击 时,需要获取cartSize 以用于逻辑目的。 useSelector() 给出一个数组cartList,其length 设置为setCartSize。 所以,当cartSize 被访问时,它正在赋予价值,落后一步。即点击&lt;button&gt;cartList 是最新的,但cartSize 是前一个值的值。

如何管理这个?如何在点击事件处理程序中使用useSelector() 的值?

EDIT-1:

// robo-list.js

const cartList = useSelector((state) => state.robo.cartItems);

{galleryItems.map((robo) => {
 <div>
  <CartButton list={cartList} item={robo} />
 </div>
...

// 机器人画廊.js

import { useDispatch } from "react-redux";

import Button from "@mui/material/Button";
import AddShoppingCartIcon from "@mui/icons-material/AddShoppingCart";

import { roboActions } from "../store/robo-slice";

function CartButton(props) {
  console.log("gal2: ",props.list.length);
  const dispatch = useDispatch();

  const onClickAddBtn = (len) => {
    console.log("gal1: ",len);
    if (props.list.length > 2) {
      alert(`cannot add more than ${props.cartList.length} material`);
    } else {
      dispatch(
        roboActions.updateCart({
          item: props.item,
          userAction: "addItemToCart",
        })
      );
    }
  };

  return (
    <Button
      variant="outlined"
      startIcon={<AddShoppingCartIcon fontSize="small" />}
      disabled={props.item.stock === 0}
      onClick={onClickAddBtn}
    >
      Add
    </Button>
  );
}
export default CartButton;

我已删除 bind() 并将 click 代码分离到另一个名为 robots-gallery.js 的文件中。我正在传递 cartList 并单击项目 robo 进入。

仍然cartList.length 落后一步。 我在这里缺少什么?请帮忙。

完整代码在这里https://codesandbox.io/s/trusting-goldberg-gcivk?file=/frontend/src/components/robo-list.js

编辑 2: // 机器人列表.js enter code herem={robo} />

// 机器人画廊.js

function CartButton(props) {
  const cartList = useSelector((state) => state.robo.cartItems);

  console.log("gal2: ",cartList.length); // 
  const dispatch = useDispatch();

  const onClickAddBtn = () => {
    console.log("gal1: ", cartList.length);
    if (cartList && cartList.length > 2) {
      alert(`cannot add more than ${cartList.length} items`);
    } else {
      dispatch(
        roboActions.updateCart({
          item: props.item,
          userAction: "addItemToCart",
        })
      );
    }
  };
  <Button
  variant="outlined"
  startIcon={<AddShoppingCartIcon fontSize="small" />}
  disabled={props.item.stock === 0}
  onClick={onClickAddBtn}
>
  Add
</Button>

cartList.length &gt; 2 落后一个更新。

【问题讨论】:

  • 为什么不只是 cartList.length?... 为什么要绑定函数?
  • cartList.length 给出了陈旧的值,与cartsize 的行为相同。我将cartObj 绑定到方法,以便将点击值(即cartObj)发送到点击处理程序。

标签: reactjs redux-toolkit


【解决方案1】:

为什么需要保持长度与状态同步?你不能这样做吗:

const CartComponent = () => {

  const cartList = useSelector((state) => state.cart.cartItems);

  const onClickAddBtn = () => {
    if(cartList && cartList.length > 4) alert(`cannot add more than ${cartList.length} items`);
  }
  return (
    <button onClick={onClickAddBtn}>
      Add
    </button>
  )
}

您还应该检查 redux 状态是否实际更新。你也许正在改变状态?一个好的做法是在你的减速器中使用immer,以确保你的状态是不可变的。如果它发生了变异,React 可能不会接受状态变化,因为对数据的引用没有改变。

【讨论】:

  • 我使用的是redux-toolkit,内部使用immer。我已经审查了代码,对我来说看起来不错,没有变异。我制作了 EDIT 2,(有问题描述)并从 中删除了useSelector,并直接在 处提取数据useSelector,遵循您的建议仍然是同样的问题。请在codesandbox.io/s/trusting-goldberg-gcivk?file=/frontend/src/…查看完整代码
【解决方案2】:

完全删除 cartSize。它总是落后一个渲染。

function CartComp(props) {
  const cartList = useSelector((state) => state.cart.cartItems);

  const onClickAddBtn = () => {
    if (cartList.length > 4) {
      alert(`cannot add more than ${cartList.length} items`);
    }
  };

  return <button onClick={onClickAddBtn}>
      Add
    </button>;
};

【讨论】:

  • cartList from const cartList = useSelector((state) =&gt; state.cart.cartItems);,总是最新的,但是cartList inside onClickAddBtn() 总是落后一步。
  • 您是否删除了bind,如图所示?还有在哪里调度更新 state.cart.cartItems 的操作?根据您的函数名称,您可能正在参加比赛。
  • 因为这会将点击句柄事件对象作为机器人参数发送到您的函数中。如果您阅读该道具的文档或记录参数,您将明白我的意思。只需使用您想要的值调用它。
  • 我更新了代码并且错误消失了,请检查有问题的编辑详细信息和更新代码的链接。你能建议吗? cartList 仍然是旧值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 2015-01-17
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 2015-09-24
相关资源
最近更新 更多