glem1337
@glem1337

Redux Field почему не срабатывает onChange?

Вызываю компонент Field из redux-form:
<Field
                id={'form__file'}
                className={'form__file form__control'}
                name={'photo'}
                type={'file'}
                label={'Upload your photo'}
                accept={'image/jpeg,image/jpg'}
                component={FileInput}
                onChange={onFileInputChange}
            />


Он в свою очередь рендерит FileInput, который рендерит Form.File из react-bootstrap:
export class FileInput extends Component {

    onChange = e => { // это никогда не срабатывает
        e.preventDefault();
        const { input: { onChange } } = this.props;
        onChange(e.target.files[0]);
    };

    render() {

        let {meta: {touched, error}, ...props} = this.props;

        return (
            <>
                <Form.File
                    custom
                    {...props.input}
                    id={props.id}
                    className={props.className}
                    label={props.label}
                    onChange={this.onChange}
                    type={props.type}
                    accept={props.accept}
                />
                {touched && error && (
                    <Form.Text className="form__error form__text">
                        {error}
                    </Form.Text>
                )}
            </>
        )
    }
};


Обработчик onFileInputChange, который должен срабатывать:
onFileInputChange = (e) => {
        e.preventDefault();
        this.setState({photo: e.target.files[0]});
        console.log(e.target.files[0]);
    };


Проблема — при клике по выбору файла приложение крашится, то есть белый экран и пустой #root элемент. Также выдает три ошибки:
1) The above error occurred in the component
2) Warning: A component is changing an uncontrolled input of type file to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
3) Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

При этом, если я размещаю поле не через Field из redux-form, а прямо в форму, то обработчик срабатывает, и все ок:
<Form.File
                id={'form__file'}
                className={'form__file form__control'}
                name={'photo'}
                type={'file'}
                label={'Upload your photo'}
                accept={'image/jpeg,image/jpg'}
                onChange={onFileInputChange}
                custom
            />


Все остальные поля валидируются и обработчики срабатывают без проблем. Если потребуется весь код, то выложу.
В гайдах в которых рассказывается как такое сделать, по сути все тоже самое.
  • Вопрос задан
  • 401 просмотр
Решения вопроса 1
glem1337
@glem1337 Автор вопроса
Нашел в чем проблема. FileInput который рендерился Field-ом через указание {...props.input} устанавливал value для поля, а этого делать нельзя. Нужно переделать вот так:
export class FileInput extends Component {

    onChange = e => { 
        e.preventDefault();
        const { input: { onChange } } = this.props;
        onChange(e.target.files[0]);
    };

    render() {

        let {meta: {touched, error}, input: {value}, ...props} = this.props; // достаем value из props.input

        return (
            <>
                <Form.File
                    custom
                    {...props.input}
                    id={props.id}
                    className={props.className}
                    label={props.label}
                    onChange={this.onChange}
                    type={props.type}
                    accept={props.accept}
                />
                {touched && error && (
                    <Form.Text className="form__error form__text">
                        {error}
                    </Form.Text>
                )}
            </>
        )
    }
};
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы