javascript - 关于这个 React 自定义钩子(Hook)用法的困惑

标签 javascript reactjs react-hooks

我正在看一些关于 React Hooks 的教程,在教程中作者创建了一个 useDropdown 钩子(Hook)来呈现可重用的下拉列表。代码是这样的

import React, { useState } from "react";

const useDropdown = (label, defaultState, options) => {
  const [state, updateState] = useState(defaultState);
  const id = `use-dropdown-${label.replace(" ", "").toLowerCase()}`;
  const Dropdown = () => (
    <label htmlFor={id}>
      {label}
      <select
        id={id}
        value={state}
        onChange={e => updateState(e.target.value)}
        onBlur={e => updateState(e.target.value)}
        disabled={!options.length}
      >
        <option />
        {options.map(item => (
          <option key={item} value={item}>
            {item}
          </option>
        ))}
      </select>
    </label>
  );
  return [state, Dropdown, updateState];
};

export default useDropdown;

他在这样的组件中使用了它

import React, { useState, useEffect } from "react";
import useDropdown from "./useDropdown";

const SomeComponent = () => {
  const [animal, AnimalDropdown] = useDropdown("Animal", "dog", ANIMALS);
  const [breed, BreedDropdown, updateBreed] = useDropdown("Breed", "", breeds);

  return (
    <div className="search-params">
      <form>
        <label htmlFor="location">
          Location
          <input
            id="location"
            value={location}
            placeholder="Location"
            onChange={e => updateLocation(e.target.value)}
          />
        </label>
        <AnimalDropdown />
        <BreedDropdown />
        <button>Submit</button>
      </form>
    </div>
  );
};

export default SomeComponent;

他说这样我们可以创建可重用的下拉组件。我想知道这与定义一个普通的旧 Dropdown 组件并将 Prop 传递给它有什么不同。在这种情况下,我能想到的唯一区别是,现在我们能够直接从那里。然而,这是否被认为是一种反模式,因为我们正在打破单向数据流?

最佳答案

虽然对于如何定义自定义钩子(Hook)以及应该包含什么逻辑没有硬核限制,但它是编写返回 JSX 的钩子(Hook)的反模式

您应该评估每种方法给您带来的好处,然后决定一段特定的代码

使用钩子(Hook)返回 JSX 有一些缺点

  • 当您编写一个返回 JSX 组件的钩子(Hook)时,您实际上是在功能组件中定义该组件,因此在每次重新渲染时,您都将创建该组件的一个新实例。这将导致组件被卸载并再次安装。如果您在组件中有状态登录,这对性能不利并且还会出现错误,因为每次重新渲染父
  • 时都会重置状态
  • 通过在钩子(Hook)中定义 JSX 组件,您可以在需要时取消延迟加载组件的选项。
  • 对组件的任何性能优化都需要您使用 useMemo这不会为您提供像 React.memo
  • 这样的自定义比较器函数的灵 active

    另一方面的好处是您可以控制父组件的状态。但是,您仍然可以通过使用受控组件方法来实现相同的逻辑
    import React, { useState } from "react";
    
    const Dropdown = Reat.memo((props) => {
      const { label, value, updateState, options } = props;
      const id = `use-dropdown-${label.replace(" ", "").toLowerCase()}`;
      return (
        <label htmlFor={id}>
          {label}
          <select
            id={id}
            value={value}
            onChange={e => updateState(e.target.value)}
            onBlur={e => updateState(e.target.value)}
            disabled={!options.length}
          >
            <option />
            {options.map(item => (
              <option key={item} value={item}>
                {item}
              </option>
            ))}
          </select>
        </label>
      );
    });
    
    export default Dropdown;
    

    并将其用作
    import React, { useState, useEffect } from "react";
    import useDropdown from "./useDropdown";
    
    const SomeComponent = () => {
      const [animal, updateAnimal] = useState("dog");
      const [breed, updateBreed] = useState("");
    
      return (
        <div className="search-params">
          <form>
            <label htmlFor="location">
              Location
              <input
                id="location"
                value={location}
                placeholder="Location"
                onChange={e => updateLocation(e.target.value)}
              />
            </label>
            <Dropdown label="animal" value={animal} updateState={updateAnimal} options={ANIMALS}/>
            <Dropdown label="breed" value={breed} updateState={updateBreed} options={breeds}/>
            <button>Submit</button>
          </form>
        </div>
      );
    };
    
    export default SomeComponent;
    

    关于javascript - 关于这个 React 自定义钩子(Hook)用法的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62186513/

    相关文章:

    javascript - jQuery srollTop 难题

    javascript - 接收错误 : xhr poll error socket. io 客户端 React

    javascript - jQuery 选择器按钮

    javascript - Map 函数返回 React 组件中包含未定义元素的数组

    reactjs - 使用 useState-hook 从内部改变样式组件

    reactjs - React hooks,每个 child 一个

    javascript - 使用 window.location 重定向不起作用

    javascript - 使用 webkitdirectory 和目录上传文件夹不适用于 safari 浏览器

    javascript - bundle.js 显示 HTML 代码而不是 javascript

    javascript - 为什么索引是来自渲染列表的类,在React Hooks中使用map函数?