简体   繁体   English

为什么 useState 值没有在 useHotkeys 回调中更新?

[英]Why does a useState value isn't updated inside useHotkeys callback?

I've got the following search suggest with React hooks that uses react-hotkeys-hooks to manage keypress.我有以下搜索建议 React hooks 使用react-hotkeys-hooks来管理按键。

Why does selectedUserItem not update on keypress Enter ?为什么selectedUserItem不在按键Enter上更新? It stays 0 while the up and down keys change.当向上和向下键改变时它保持为 0。

import { useHotkeys } from "react-hotkeys-hook";
import React, { useState } from "react";

import "./styles.css";
const itemsByName = [
  {
    id: 1,
    name: "Ice Cream"
  },
  {
    id: 2,
    name: "Banana Pudding"
  },
  {
    id: 3,
    name: "Chocolate Cake"
  },
  {
    id: 4,
    name: "Sponge Cake"
  },
  {
    id: 5,
    name: "Carrot Cake"
  }
];

const App = () => {
  const [selectedUserItem, setSelectedUserItem] = useState(0);

  // const [create] = useMutation(SAVE_USER_ITEM, {
  //   refetchQueries: ["UserItemsQuery"]
  // })

  const itemSelect = (e, item) => {
    e.preventDefault();
    // create({ variables: { input: { id: item.id } } });
    // console.log(item)
  };

  const increment = selectedUserItem => {
    const max = itemsByName.length - 1;
    return max > selectedUserItem ? selectedUserItem + 1 : max;
  };

  const decrement = selectedUserItem => {
    const min = 0;
    return min < selectedUserItem ? selectedUserItem - 1 : min;
  };

  useHotkeys(
    "*",
    (event, handler) => {
      // console.log(handler)
      switch (event.key) {
        case "ArrowDown":
          setSelectedUserItem(selectedUserItem => increment(selectedUserItem));
          break;
        case "ArrowUp":
          setSelectedUserItem(selectedUserItem => decrement(selectedUserItem));
          break;
        case "Enter":
          console.log(selectedUserItem);
          const userItem = itemsByName[selectedUserItem];
          console.log(userItem);
          break;
        default:
          console.log(event.key);
          break;
      }
    },
    {
      filter: () => true
    }
  );

  return (
    <div className="absolute w-3/4 mt-16 ml-8 py-2 bg-white shadow-xl rounded-lg">
      <h1>Index: {selectedUserItem}</h1>
      {itemsByName.map((item, i) => {
        return (
          <div
            href="#"
            onClick={e => itemSelect(e, item)}
            className={`${selectedUserItem === i ? "hovered" : ""} dessert`}
            key={item.id}
          >
            {item.id}: {item.name}
          </div>
        );
      })}
    </div>
  );
};

export default App;

useHotkeys internals use the useCallback and useEffect hooks, which need to know when some of its dependencies change. useHotkeys内部使用useCallbackuseEffect钩子,这需要知道它的某些依赖项何时发生变化。 To make sure it works well with these hooks,useHotkeys offers to pass a deps array , like the other hooks mentioned, as its last parameter.为了确保它与这些钩子一起工作良好,useHotkeys提供传递一个deps array ,就像提到的其他钩子一样,作为它的最后一个参数。

deps: any[] = [] : The dependency array that gets appended to the memoization of the callback. deps: any[] = [] :附加到回调记忆的依赖数组。 Here you define the inner dependencies of your callback.在这里您定义回调的内部依赖关系。 If for example your callback actions depend on a referentially unstable value or a value that will change over time, you should add this value to your deps array.例如,如果您的回调操作依赖于一个引用不稳定的值或一个会随时间变化的值,您应该将此值添加到您的deps数组中。 Since most of the time your callback won't depend on any unstable callbacks or changing values over time you can leave this value alone since it will be set to an empty array by default.由于大多数时候你的回调不会依赖于任何不稳定的回调或随时间变化的值,你可以不理会这个值,因为它默认设置为空数组。

In your code, it would looks like this:在您的代码中,它看起来像这样:

// These never changes and do not rely on the component scope, so they
// can be defined safely outside the component.
const increment = selectedUserItem => {
  const max = itemsByName.length - 1;
  return max > selectedUserItem ? selectedUserItem + 1 : max;
};

const decrement = selectedUserItem => {
  const min = 0;
  return min < selectedUserItem ? selectedUserItem - 1 : min;
};

const App = () => {
  const [selectedUserItem, setSelectedUserItem] = useState(0);

  useHotkeys(
    "*",
    (event, handler) => {
      switch (event.key) {
        case "ArrowDown":
          setSelectedUserItem(increment);
          break;
        case "ArrowUp":
          setSelectedUserItem(decrement);
          break;
        case "Enter":
          console.log(selectedUserItem, itemsByName[selectedUserItem]);
          break;
        default:
          console.log(event.key);
          break;
      }
    },
    {
      filter: () => true
    },
    // The dependencies array which ensure that the data is up to date in the callback.
    [selectedUserItem, setSelectedUserItem]
  );

  // rest of the component

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM