【问题标题】:How can I make this react input component idiomatic?我怎样才能使这个反应输入组件惯用?
【发布时间】:2019-08-15 04:01:39
【问题描述】:

这是一个反应输入组件:

function Input({ value, setValue }) {
  return (
    <div>
      <input value={value} onChange={event => setValue(event.target.value)} />
      <button onClick={() => setValue(value.toUpperCase())}>Capitalize</button>
    </div>
  );
}

它只是一个普通的输入组件和一个将输入值大写的按钮。它意味着由一些父组件控制:

function Parent() {
  let [value, setValue] = useState("");
  return <Input value={value} setValue={setValue} />;
}

这很好用,但它不是惯用的。要用作普通输入组件的“插入式替换”,它应该采用 onChange 属性,而不是 setValue,相关区别在于 onChange 采用合成事件作为参数,而 setValue接受一个字符串。 (我希望大写按钮的存在对于使用此Input 组件的开发人员来说是“不透明的”。)

我试图通过在单击按钮时让输入元素触发更改事件来惯用这一点(参见下面的 sn-p),但这不会导致 onChange 执行。 (我认为这是由于我不理解 react 的合成事件系统的细节。我浏览了很多关于这个主题的帖子,但无法得到我发现的想法。)

function AnotherInput({ value, onChange }) {
  let input = useRef();

  let handleClick = () => {
    input.current.value = value.toUpperCase();

    var event = new Event("change" /* also tried "input" */, {
      bubbles: true
    });

    input.current.dispatchEvent(event); // onChange doesn't fire!
  };
  return (
    <div>
      <input value={value} ref={input} onChange={onChange} />
      <button onClick={handleClick}>Capitalize</button>
    </div>
  );
}

另外,我觉得我不应该在这里使用ref,因为我不想直接修改DOM;我只想更改控制父组件中的值。

Here's a CodePen.

【问题讨论】:

    标签: javascript reactjs dom-events react-hooks


    【解决方案1】:

    我通过模拟大写按钮上的event Object 使其工作。

    父组件:

    function Parent() {
        let [value, setValue] = useState("");
        return <Input value={value} onChange={(e) => setValue(e.target.value)} />;
    }
    

    输入组件:

    已编辑:我设法为输入组件想出了一个更优雅的解决方案:

     function Input({ value, onChange: inheritedOnChange }) {
        return (
            <div>
                <input value={value} onChange={inheritedOnChange} />
                <button value={value.toUpperCase()} onClick={inheritedOnChange}>Capitalize</button>
            </div>
        );
    }
    

    请注意,我将 onChange 属性重命名为 inheritedOnChange 只是为了便于阅读。在解构时保留 onChange 名称应该仍然有效。

    【讨论】:

    • 您的第二个解决方案特别聪明!我不知道button 标签有value 属性。传递给onChange 的事件目标会有所不同(inputbutton),但这似乎很合理,准确地反映了事件的来源......
    • 另外,它是第二个示例的父级上onChange 的定义(不在@Japsz 的sn-p 中),您需要阅读event.currentTarget.value 而不是简单的event.target.value。 (这花了我 20 分钟。)
    猜你喜欢
    • 2022-11-01
    • 2015-02-07
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多