使用Formik降档自动完成onBlur重置值

时间:2019-03-06 15:48:38

标签: reactjs formik yup downshift

我有一个表单,其中的字段需要通过api调用显示建议。应该允许用户选择这些选项之一,也可以选择键入的值与表单一起提交,但是此字段是必需的。我正在使用Formik来处理表单,是使用Yup进行表单验证以检查是否需要此字段,降级用于自动完成功能,而Material-UI则用于该字段。

当用户决定不使用建议的选项之一和onBlur触发器时,就会出现问题。 onBlur总是会重置该字段,我认为这是导致这种行为的降档,但是解决此问题的方法建议控制降档的状态,当我尝试它不能与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} />}
        />
    );
}

1 个答案:

答案 0 :(得分:2)

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

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

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