首页 > 解决方案 > OnFocus 事件未触发 React Final Form 中的自定义组件

问题描述

大家早上好,所以我在使用 React Final Form 时遇到了一些困难,即使我已经浏览了文档,我仍然没有设法解决我的问题。

所以我只是在玩 React Final Forms 并试图弄清楚它是如何工作的,但是我遇到了一些关于自定义组件和触发 onFocus、onChange 和 onBlur 事件的问题。

这是我的自定义自动完成组件

import React, {useState} from 'react';
import {differenceWith, find, isEqual} from 'lodash';

import MenuGroup from '../MenuGroup';
import OutsideClickHandler from '../OutsideClickHandler';
import TagGroup from '../TagGroup';
import Text from '../Text';
import TextField from '../TextField';

const Autocomplete = ({id, label, options, minimumSearchValue}) => {
    const [isMenuPanelVisible, setIsMenuPanelVisible] = useState(false);
    const [selectedOptions, setSelectedOptions] = useState([]);
    const [searchValue, setSearchValue] = useState('');

    const hasMinSearchValue = (value = searchValue) => {
        return value.length >= minimumSearchValue;
    }

    const onSearchInputFocus = (e) => {
        const {value} = e.target;  
        setSearchValue(value);
        if (hasMinSearchValue(value) && !isMenuPanelVisible) return setIsMenuPanelVisible(true);
    }

    const onSearchInputChange = (e) => {
        const {value} = e.target;
        setSearchValue(value);
        if (hasMinSearchValue(value)) return setIsMenuPanelVisible(true);
    }

    const closeMenuPanel = () => {
        setIsMenuPanelVisible(false);
    }

    const getMenuOptions = () => differenceWith(options, selectedOptions, isEqual);
    
    const addSelectedOption = ({value}) => {
        if (!find(selectedOptions, {value})) {
            setSelectedOptions( options => [...options, {value}]);
        }
    }
    
    const removeSelectedOption = ({value}) => {
        setSelectedOptions(selectedOptions.filter(item => item.value !== value));
    }

    const renderSearchField = () => (
        <TextField name={id} label={label} onSearchFocus={onSearchInputFocus} onSearchChange={onSearchInputChange} errorMessage={'There has been an error'} />
    )

    const renderSearchMenu = () => {
        if (isMenuPanelVisible) return <MenuGroup options={getMenuOptions()} onMenuGroupClick={addSelectedOption} />
    }

    const renderSelectedOptions = () => (
            <TagGroup options={selectedOptions} onTagGroupClick={removeSelectedOption} />
    )

    const renderMinimumCharacterMessage = () => {
        if (minimumSearchValue === 0) {
            return null;
        }

        if (!hasMinSearchValue() && searchValue >= 1) {
            return (
                <Text type='p'>{`Minimum of ${minimumSearchValue} characters required`}</Text>
            )
        }
    }

    const renderNoResultsMessage = () => {
        return (
            <Text type='p'>No results found</Text>
        )
    }

    return (
        <>
            <OutsideClickHandler onOutsideClick={closeMenuPanel}>
                {renderSearchField()}
                {renderSearchMenu()}
            </OutsideClickHandler>
            {renderNoResultsMessage()}
            {renderSelectedOptions()}
            {renderMinimumCharacterMessage()}
        </>
    )
}

export default Autocomplete;

这是一个使用 React Final Form 的 Form 组件的基本示例

import React from 'react';
import {Form, Field} from 'react-final-form';

import AutocompleteFormAdapter from '../../subModules/Autocomplete/AutocompleteFormAdapter';

const ComplexForm = () => {
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const onSubmit = async (values) => {
        await sleep(300);
        window.alert(JSON.stringify(values, 0, 2));
    }
    const formData = {};

    return (
        <Form 
            initialValues={formData}
            onSubmit={onSubmit}
            render={({form, values, handleSubmit}) => {
                return (
                    <form>
                        <Field name='testField' component={AutocompleteFormAdapter} />

                        <div>
                            <button onClick={handleSubmit}>Submit</button>
                            <button onClick={form.reset}>Reset</button>
                        </div>
                        <pre>{JSON.stringify(values, 0, 2)}</pre>
                    </form>
                )
            }} >
        </Form>
    )
}

export default ComplexForm;

这是自动完成的适配器

import React from 'react';

import Autocomplete from '../../subModules/Autocomplete';

import data from '../../documentation/ComplexForm/data.json';

const AutocompleteFormAdapter = ({input, ...rest}) => {
    const autocompleteOptions = data;

    const mapDataToViewModel = (data) => ({
        value: data.attributes.name,
        key: data.id,
    });

    const filteredOptions = autocompleteOptions.map(mapDataToViewModel);

    return (
        <Autocomplete {...input} {...rest} options={filteredOptions} minSearchLength={0} onFocus={(event, value) => {
            console.log('** Event: ', event);
            console.log('** Value: ', value);

            input.onFocus(event, value);
        }} />
    )
}

export default AutocompleteFormAdapter;

我已经尝试了很多不同的方法来触发自动完成适配器中的 onFocus 事件,但它只是没有它,我做错了什么?

标签: javascriptreactjsreact-final-form

解决方案


推荐阅读