【问题标题】:Why does React Hook Form think field not filled in with Chakra UI?为什么 React Hook Form think field 没有用 Chakra UI 填充?
【发布时间】:2022-01-21 02:17:59
【问题描述】:

我在 React 中构建了一个自动完成输入,使用 Chakra UI 进行样式设置。我还使用 react-hook-form 来处理表单提交钩子。

当我使用自动完成填写表格时,我可以成功地从下拉列表中选择一个选项。但是,在提交表单时,React-Hook-Form 似乎认为我没有填写这些字段,因为没有提交任何内容并且没有调用 onSubmit 调用。

我使用 forwardRef 将 ref 传递给输入,这应该是注册这些字段所需要的全部内容。


这是一个沙箱,可以让调试更容易 - 请注意,提交时没有调用日志,RHF 也没有任何错误 - 应该出现两者之一 - https://codesandbox.io/s/chakra-hook-fail-49ppb


表格代码为:

const test: AutoCompleteSuggestions[] = [
    {key: "US", value: "USA"},
    {key: "UK", value: "United Kingdom"},
]
function onSubmit(values: QueryFormParams) {
    console.log('V'); //Never gets called
}
return (

                <form onSubmit={handleSubmit(onSubmit)}>
                    <FormControl isInvalid={errors.name}>
                                <AutoComplete
                                    {...register('selectedDeparture', {
                                        required: 'Select a departure',
                                    })}
                                    placeholder={'Departure country...'}
                                    isValid={v => setIsItemSelected(v)}
                                    suggestions={test}
                                />
                    </FormControl>
              </form>
)

自动补全代码如下:

import React, {Ref, useState} from 'react';
import {Input, Table, Tbody, Td, Tr, VStack} from '@chakra-ui/react';

type AutoCompleteProps = {
    suggestions: AutoCompleteSuggestions[]
    isValid: (b: boolean) => void
    placeholder: string
}

export type AutoCompleteSuggestions = {
    key: string,
    value: string
}

// eslint-disable-next-line react/display-name
export const AutoComplete = React.forwardRef(({suggestions, isValid, placeholder}: AutoCompleteProps, ref: Ref<HTMLInputElement>) => {
    
    const [filteredSuggestions, setFilteredSuggestions] = useState<AutoCompleteSuggestions[]>();
    const [showSuggestions, setShowSuggestions] = useState<boolean>(false);
    const [userInput, setUserInput] = useState<string>('');

    function onChange(e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) {
        console.log('Changing', userInput, e.currentTarget.value);
        const newUserInput = e.currentTarget.value;
        if (!newUserInput) {
            //setActiveSuggestion(-1);
            setFilteredSuggestions([]);
            setShowSuggestions(false);
            isValid(true);
            setUserInput(e.currentTarget.value);
        }
        const filteredSuggestions = suggestions.filter(suggestion => suggestion.value.toLowerCase().startsWith(userInput.toLowerCase()));
        //setActiveSuggestion(e.target.innerText);
        setFilteredSuggestions(filteredSuggestions);
        setShowSuggestions(true);
        isValid(false);
        setUserInput(e.currentTarget.value);
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    function onClick(e: MouseEvent<HTMLLIElement, MouseEvent>) {
        console.log('Clicked', e.target.innerText);
        setFilteredSuggestions([]);
        setShowSuggestions(false);
        isValid(true);
        setUserInput(e.target.innerText);
    }

    let suggestionsListComponent;

    if (showSuggestions && userInput) {
        if (filteredSuggestions?.length) {
            suggestionsListComponent = (
                <Table className={'suggestions'} position={'absolute'} top={10} left={0} right={0} variant='simple' zIndex={999}>
                    <Tbody>
                        {filteredSuggestions?.map((suggestion, index) => {
                            return (
                                <Tr key={index}
                                    _hover={{
                                        background: 'gray.200',
                                        color: 'green',
                                    }}
                                    onClick={onClick}>
                                    <Td>
                                        <span className={'selectedText'}>{suggestion.value}</span>
                                    </Td>
                                </Tr>
                            );
                        })}
                    </Tbody>
                </Table>
            );
        } else {
            suggestionsListComponent = (
                <div className="no-suggestions">
                    <em>No countries found for that input!</em>
                </div>
            );
        }
    }

    return (
        <>
            <VStack position={'relative'}>
                <Input
                    ref={ref}
                    type="text"
                    onChange={onChange}
                    value={userInput}
                    placeholder={placeholder}
                />
                {suggestionsListComponent}
            </VStack>
        </>
    );
});

export default AutoComplete;

【问题讨论】:

  • 应该有codeandbox演示,因为它有很多代码,我还是不明白你的问题是什么:(
  • codesandbox.io/s/chakra-hook-fail-49ppb @TanNguyen 看到这个沙箱 - 提交时没有调用日志,也没有显示错误
  • 把它放到你的帖子(在头),以便其他人可以看到^^
  • 是我自己还是 CodeSandbox 不工作?
  • @whygee 请立即查看

标签: javascript reactjs react-hooks react-hook-form chakra-ui


【解决方案1】:

我通过添加控制器解决了这个问题

                                <Controller
                                    control={control}
                                    name="selectedDeparture"
                                    rules={{required: true}}
                                    render={({field: {onChange, value}}) => (
                                        <AutoComplete
                                            onChange={(event, item) => {
                                                onChange(item);
                                            }}
                                            placeholder={'Departure country...'}
                                            isValid={v => setIsItemSelected(v)}
                                            suggestions={countriesMap}
                                        />
                                    )}
                                />

【讨论】:

    猜你喜欢
    • 2021-04-10
    • 2022-12-28
    • 2020-05-23
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 2021-12-16
    • 2017-01-18
    • 2020-04-28
    相关资源
    最近更新 更多