如何获取表单中自定义输入组件的值?

huangapple go评论77阅读模式
英文:

How to get the value of a custom input component inside a form?

问题

我在React TypeScript中编写了一个小的自定义组件,它包装了一个带有额外功能的<input />,主要用于在一组选项中进行模糊搜索。我计划在表单内部使用这个组件。

然而,现在我创建了这个组件,我无法在<form>内部检索其值,因为它不是HTML元素,没有我可以读取的value属性。

我阅读了这里的文档,但没有帮助我。我还尝试了Google搜索诸如“在React表单中的自定义输入”、“从自定义React组件获取值”等内容,但没有找到任何结果,尽管我确定这应该是许多人遇到的一个非常简单的问题。我找到的最接近的结果是这个,但答案对我没有帮助。

这是我的组件:

export interface SmartInputProps {
    items: any[],
    itemKey: string
    //[...]
}

export const SmartInput: React.FC<SmartInputProps> = ({
    items,
    itemKey = 'name'
    //[...]
}: SmartInputProps) => {

    // [...]
    //(很多功能)

    return (
        <div>
            <input /*[...]*/ />
            //一些其他可视化内容,比如显示结果列表
        </div>
    );
}

以及我想在其中使用该组件的表单:

interface Props {
    className?: string
}

export const SearchBar: React.FC<Props> = () => {
    // [...]

    return (
        <div className="searchbar-wrapper">
            <form onSubmit={handleSubmit}>
                <SmartInput
                    items={options}
                    itemKey='name' 
                    //[...]
                />
                <input type='submit' value='OK' />
            </form>
        </div>
    );
}

我想在表单中访问位于<SmartInput />内部的<input />的当前value。我尝试使用一些hacky的方法来获取这个值,比如将<input />onChange委托给上层(正如这里提出的),但这只允许我在每次onChange触发时获取并存储该值,而不是在提交时读取它。这种解决方法确实允许我在提交时使用该值,但我必须首先处理每个onChange,这不是最佳方法。

英文:

I wrote a small custom component in react-ts that wraps an &lt;input /&gt; with some additional functionality, mainly fuzzy searching through a list of options. I am planning to use this inside a form.

However now that I created the component, I can not retrieve its value inside a &lt;form&gt;, since it is not a html element and has no value attribute that i can read.

I am reading the docs here, but it is not helping me. I also tried googling things like "custom input in react form", "get value from custom react component" etc. but could not find any results, although I am sure this should be a pretty straight-forward thing happening to a lot of people. the closest result I could find was this and the answers did not help me at all.

the component:

export interface SmartInputProps {
    items: any[],
    itemKey: string
    //[...]
}

export const SmartInput: React.FC&lt;SmartInputProps&gt; = ({
    items,
    itemKey = &#39;name&#39;
    //[...]
}: SmartInputProps) =&gt; {

    // [...]
    // (lots of funcionality)

    return (
        &lt;div&gt;
            &lt;input /*[...]*/ /&gt;
            //some more visual stuff, like displaying list of results
        &lt;/div&gt;
    );
}

And the form I want to use the component in

interface Props {
    className?: string
}

export const SearchBar: React.FC&lt;Props&gt; = () =&gt; {
    // [...]
    
    return (
        &lt;div className=&quot;searchbar-wrapper&quot;&gt;
            &lt;form onSubmit={handleSubmit}&gt;
                &lt;SmartInput
                    items={options}
                    itemKey=&#39;name&#39; 
                    //[...]
                /&gt;
                &lt;input type=&#39;submit&#39; value=&#39;OK&#39; /&gt;
            &lt;/form&gt;
        &lt;/div&gt;
    );
}

I would like to access the current value of the &lt;input /&gt; that is inside &lt;SmartInput /&gt; in the form.

I tried using hacky ways of getting the value, such as delegating the onChange of the &lt;input /&gt; upwards (as proposed here), but that only allows me to get and store the value whenever onChange is triggered, not read it at submit-time. This workaround does allow me to use the value at submit-time but I have to handle every single onChange first which is sub-optimal.

答案1

得分: 0

我找到了一个更好的解决方案,使用 useRef ,这也更加优雅。

使用最初的示例:

interface Props {
    className?: string
}

export const SearchBar: React.FC<Props> = () => {
    const inputRef = useRef<HTMLInputElement>(null); // 在这里
    // [...]

    return (
        <div className="searchbar-wrapper">
            <form onSubmit={handleSubmit}>
                <SmartInput
                    items={options}
                    itemKey='name'
                    ref={inputRef}   // 在这里
                    //[...]
                />
                <input type='submit' value='OK' />
            </form>
        </div>
    );
}

我们向组件添加了一个带有输入类型接口的 useRef。然后,将其作为属性传递给自定义组件 <SmartInput />

在接收组件的一侧:

export interface SmartInputProps {
    items: any[],
    itemKey: string,
    ref: MutableRefObject<HTMLInputElement> // 在这里
    //[...]
}

export const SmartInput: React.FC<SmartInputProps> = ({
    items,
    itemKey = 'name',
    ref, // 在这里
    //[...]
}: SmartInputProps) => {

    // [...]
    // (很多功能)

    return (
        <div>
            <input ref={ref} /* 在这里 */ /*[...]*/ />
            //一些其他可视化内容,如显示结果列表
        </div>
    );
}

我们将引用添加到自定义组件的属性,并将其传递给自定义组件内部的原生HTML输入字段的 ref 属性。

现在,我们可以从根引用对象查询字段状态。

例如:let fieldValue = inputRef.current.value

英文:

I found a better solution using useRef which is also more elegant.

Using the initial examples:

interface Props {
    className?: string
}

export const SearchBar: React.FC&lt;Props&gt; = () =&gt; {
    const inputRef = useRef&lt;HTMLInputElement&gt;(null); //&lt;- here
    // [...]
    
    return (
        &lt;div className=&quot;searchbar-wrapper&quot;&gt;
            &lt;form onSubmit={handleSubmit}&gt;
                &lt;SmartInput
                    items={options}
                    itemKey=&#39;name&#39;
                    ref={inputRef}   //&lt;- here
                    //[...]
                /&gt;
                &lt;input type=&#39;submit&#39; value=&#39;OK&#39; /&gt;
            &lt;/form&gt;
        &lt;/div&gt;
    );
}

We add a useRef with the input type interface to the component. then we pass it to the custom component &lt;SmartInput /&gt; as a prop.

On the side of the receiving component:

export interface SmartInputProps {
    items: any[],
    itemKey: string,
    ref: MutableRefObject&lt;HTMLInputElement&gt; //&lt;- here
    //[...]
}

export const SmartInput: React.FC&lt;SmartInputProps&gt; = ({
    items,
    itemKey = &#39;name&#39;,
    ref, //&lt;- here
    //[...]
}: SmartInputProps) =&gt; {

    // [...]
    // (lots of funcionality)

    return (
        &lt;div&gt;
            &lt;input ref={ref} /*&lt;- here*/ /*[...]*/ /&gt;
            //some more visual stuff, like displaying list of results
        &lt;/div&gt;
    );
}

We add the ref to the custom component props and pass it to the ref attribute of the vanilla html input field inside our custom component.

No we can query the field state from the root ref object.

e.g. let fieldValue = inputRef.current.value.

huangapple
  • 本文由 发表于 2023年3月7日 03:13:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75654915.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定