2

我有一个需要通过 api 调用显示建议的字段的表单。应该允许用户选择或不选择其中一个选项,并且他们输入的值用于与表单一起提交,但此字段是必需的。我正在使用 Formik 来处理表单,是的用于表单验证以检查是否需要此字段,用于自动完成的降档,以及用于字段的 Material-UI。

当用户决定不使用建议的选项之一和 onBlur 触发器时,就会出现问题。onBlur 总是重置该字段,我相信这是 Downshift 导致了这种行为,但是这个问题的解决方案建议控制 Downshift 的状态,当我尝试它不能很好地与 Formik 和 Yup 一起工作时,我可以解决一些问题' 不是很明白,因为这些组件控制着这个字段的 inputValue。

继承人我到目前为止:

const AddBuildingForm = props => {
    const [suggestions, setSuggestions] = useState([]);
    const { values,
        errors,
        touched,
        handleChange,
        handleBlur,
        handleSubmit, 
        modalLoading,
        setFieldValue,
        setFieldTouched,
        classes } = props;

    const loadOptions = (inputValue) => {  
        if(inputValue && inputValue.length >= 3 && inputValue.trim() !== "")
        {
            console.log('send api request', inputValue)
            LocationsAPI.autoComplete(inputValue).then(response =>  {
                let options = response.data.map(erlTO => { 
                    return {
                        label: erlTO.address.normalizedAddress,
                        value: erlTO.address.normalizedAddress
                    }
                });
                setSuggestions(options);
            });
        }
        setFieldValue('address', inputValue); // update formik address value
    }

    const handleSelectChange = (selectedItem) => {
        setFieldValue('address', selectedItem.value); // update formik address value
    }

    const handleOnBlur = (e) => {
        e.preventDefault();
        setFieldValue('address', e.target.value);
        setFieldTouched('address', true, true);
    }

    const handleStateChange = changes => {
        if (changes.hasOwnProperty('selectedItem')) {
            setFieldValue('address', changes.selectedItem)
          } else if (changes.hasOwnProperty('inputValue')) {
            setFieldValue('address', changes.inputValue);
          }
    }

    return (
        <form onSubmit={handleSubmit} autoComplete="off">
            {modalLoading && <LinearProgress/>}
            <TextField
                id="name"
                label="*Name"
                margin="normal"
                name="name"
                type="name"
                onChange={handleChange}
                value={values.name}
                onBlur={handleBlur}
                disabled={modalLoading}
                fullWidth={true}
                error={touched.name && Boolean(errors.name)}
                helperText={touched.name ? errors.name : ""}/> 
            <br/>
            <Downshift  id="address-autocomplete"
                onInputValueChange={loadOptions}
                onChange={handleSelectChange}
                itemToString={item => item ? item.value : '' }
                onStateChange={handleStateChange}
               >
                {({
                        getInputProps,
                        getItemProps,
                        getMenuProps,
                        highlightedIndex,
                        inputValue,
                        isOpen,
                    }) => (
                        <div>
                            <TextField
                                id="address"
                                label="*Address"
                                name="address"
                                type="address"
                                className={classes.autoCompleteOptions}
                                {...getInputProps( {onBlur: handleOnBlur})}
                                disabled={modalLoading}
                                error={touched.address && Boolean(errors.address)}
                                helperText={touched.address ? errors.address : ""}/>
                            <div {...getMenuProps()}>
                                {isOpen ? (
                                    <Paper className={classes.paper} square>
                                        {suggestions.map((suggestion, index) =>
                                            <MenuItem {...getItemProps({item:suggestion, index, key:suggestion.label})} component="div"  >
                                                {suggestion.value}
                                            </MenuItem>
                                        )}
                                    </Paper>
                                ) : null}
                            </div>
                        </div>
                )}                
            </Downshift>

            <Grid container direction="column" justify="center" alignItems="center">
                <Button id="saveBtn"
                        type="submit" 
                        disabled={modalLoading} 
                        className = {classes.btn}
                        color="primary" 
                        variant="contained">Save</Button>
            </Grid>
        </form>
    );
}

const AddBuildingModal = props => {
    const { modalLoading, classes, autoComplete, autoCompleteOptions } = props;
    return(
        <Formik
            initialValues={{ 
                name: '', 
                address: '',
            }}
            validationSchema={validationSchema}
            onSubmit = {
                (values) => {
                    values.parentId = props.companyId;
                    props.submitAddBuildingForm(values);
                }
            }
            render={formikProps => <AddBuildingForm 
                                        autoCompleteOptions={autoCompleteOptions}
                                        autoComplete={autoComplete} 
                                        classes={classes} 
                                        modalLoading={modalLoading}
                                        {...formikProps} />}
        />
    );
}
4

1 回答 1

3

让它工作。需要使用 handleOuterClick 并使用 Formik 值设置 Downshift 状态:

const handleOuterClick = (state) => {
    // Set downshift state to the updated formik value from handleOnBlur
    state.setState({
        inputValue: values.address
    })
}

现在,每当我单击时,该值都会保留在输入字段中。

于 2019-03-13T16:51:48.093 回答