【问题标题】:How do i add a dropdown to useEffects?如何向 useEffects 添加下拉列表?
【发布时间】:2020-01-07 16:34:13
【问题描述】:

我是 react 和 office-ui-fabric 的新手,在理解如何向 useEffect 添加下拉列表时遇到问题。用户从下拉列表中选择选项,我需要 useEffects 来监视选择给另一个用户的值,以便我可以将选择的值发送给另一个函数。

const options: IDropdownOption[] = [
  { key: "A", text: "A", itemType: DropdownMenuItemType.Header },
  { key: "B", text: "B" },
  { key: "C", text: "C" }
];

const [selectedItem, setOption] = React.useState("");

React.useEffect(() => {
  window.addEventListener("message", ev => {
    switch (ev.data.command) {
      case "selectedItem": {
        console.log(`Got message`);
        setOption(ev.data.payload);
        break;
      }
    }
  });
}, []);

let test = () => {
  console.log("Test");
  vscode.postMessage({
    command: "setOption",
    text: "select option"
  });
  window.console.log(`Sent message.`);
};

return (
  <div>
    <Stack>
      <Stack.Item grow>
        <Label style={{ color: "white" }}>Select Option</Label>
        <Dropdown
          placeholder="Select option"
          options={options}
          styles={dropdownStyles}
          selectedKey={selectedItem}
          onChanged={selectedOption => {
            setOption(selectedOption.text);
            console.log(selectedOption.text);
            test;
          }}
        />
      </Stack.Item>
    </Stack>
    `enter code here`
  </div>
);

目前我没有看到 test() 中的日志“测试”或任何日志“得到消息”等,这意味着测试没有被触发。这是正确的方法吗?还是我应该有一个类似 onClick 的测试功能?

【问题讨论】:

    标签: typescript office-ui-fabric react-tsx


    【解决方案1】:

    您的test 函数没有触发,因为您没有调用它;你有裸令牌test,而不是函数调用test()

    与其直接在事件处理程序中连接副作用处理程序,不如使用useEffect(最好称为useSideEffect)并指定您希望它在您更改selectedItem时触发:

    // Whenever the value of selectedItem changes, fire this callback
    // selectedItem will change as a consequence of setOption() being called
    React.useEffect(() => {
        vscode.postMessage({
            command: "setOption",
            text: selectedItem
        });
    }, [selectedItem])
    
    // Define a callback with a hook, so we don't generate a new
    // anonymous function every render
    const onItemChanged = React.useCallback(e => setOption(e.text), [setOption]);
    
    <Dropdown ... onChanged={onItemChanged} />
    

    useEffect 的第二个参数是要监控的值列表。当此组件重新渲染,并且任何列出的项目的值发生变化时,将调用定义的函数。

    通过使用 useCallback 定义回调函数,而不是在每次重新渲染组件时都重新定义的匿名函数,您将避免额外的垃圾生成,并且可以轻松地保留“在此情况下要做的事情”的逻辑列表一起改变”。

    【讨论】:

    • 感谢您的建议!我尝试实现它并在 const onItemChanged = React.useEffect(e => setOption(e.text), [setOption]); 行遇到错误错误是 (e:any)=>void 类型的参数不能分配给 'EffectCallback' 类型的参数。这是否意味着我应该改用 React.useCallback?
    • 谢谢!这解决了我遇到的问题,但是当我使用 React.useCallback 时,我还可以看到从下拉列表中选择的当前和上一个选项的日志。 useCallback 是否只存储以前的值,或者我是否应该关心是否传递了正确的值?
    • React 钩子有点有趣,因为它们在以前的值上创建了闭包;您需要在挂钩内引用的任何值都需要在作为第二个参数传递的列表中。否则,您将从旧版本的钩子中获得陈旧的值。我建议将 eslint-plugin-react-hooks 添加到您的 eslint 设置中,这将帮助您捕获需要添加到监视值列表中的引用值。
    【解决方案2】:

    在 useEffect 声明的末尾,有你放在那里的空括号。这就是你需要放置效果的所有依赖项(=triggers)的地方,例如selectedItem 在这种情况下。

    目前,空数组告诉它永远不会再次触发。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      • 2020-01-24
      • 2012-02-18
      • 1970-01-01
      相关资源
      最近更新 更多