редукс-форма не может вводить значения в поля

Я не могу вводить значения в поля ввода, используя избыточную форму. У меня есть следующий редуктор

import {combineReducers} from 'redux';
import session from './sessionReducer';
import profile from './profileReducer';
import map from './mapReducer';
import { reducer as formReducer } from 'redux-form'

const rootReducer = combineReducers({
    // short hand property names
    session,
    profile,
    map,
    form: formReducer
})

export default rootReducer;

а вот и магазин

import { createStore, combineReducers, applyMiddleware } from 'redux'
import createLogger from 'redux-logger'
import thunk from 'redux-thunk'
import { routerReducer, routerMiddleware, push } from 'react-router-redux'
import reducers from '../reducers'
import { browserHistory } from 'react-router';

const middleware = [ thunk ];
if (process.env.NODE_ENV !== 'production') {
    middleware.push(createLogger());
}

middleware.push(routerMiddleware(browserHistory));


// Add the reducer to your store on the `routing` key
const store = createStore(
    combineReducers({
        reducers,
        routing: routerReducer
    }),
    applyMiddleware(...middleware),

)

export default store;

составная часть

import React, {PropTypes, Component} from 'react';
import Upload from './Upload';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as profileActions from '../../../actions/profileActions';
import EventsCalendar from '../../common/EventsCalendar';
import { Field, reduxForm } from 'redux-form'
import ProfileForm from './ProfileForm';

import {
    Form,
    FormGroup,
    FormControl,
    ControlLabel,
    Tabs,
    Tab,
    InputGroup,
    Label,
    HelpBlock,
    Grid,
    Row,
    Button,
    Col

} from 'react-bootstrap';


class Profile extends Component {

    static propTypes = {
        profile: PropTypes.object.isRequired,
    };

    constructor(props) {
        super(props);

        this.state = {
            profile: {
                username: '',
                password: '',
                email: ''
            }
        }
        //this.onUpdate = this.onUpdate.bind(this)
    }

    handleSubmit = (values) => {
        // Do something with the form values
        console.log(values);
    }

    componentDidMount() {
        this.props.actions.getProfile()
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.profile !== this.props.profile) {

        }
    }

    render() {
        console.log(this.props.profile);
        const {profile} = this.props.profile;
        const { handleSubmit } = this.props;

        return (
            <div className="row">
                <Col lg={10}>
                    <Tabs defaultActiveKey={1} id="uncontrolled-tab-example">
                        <Tab eventKey={1} title="Vendor Data">
                            <ProfileForm onSubmit={this.handleSubmit}  data = {this.props.profile}/>
                        </Tab>
                        <Tab eventKey={3} title="Events Calendar">
                            <EventsCalendar/>
                        </Tab>
                    </Tabs>

                </Col>

                <Col lg={2}>
                    <Upload/>
                </Col>
            </div>
        );
    }
}

function mapStateToProps(state) {

    return {
        profile: state.default.profile,
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(profileActions, dispatch)
    };
}

Profile = reduxForm({
    form: 'profileForm' // a unique name for this form
})(Profile);

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

когда я печатаю, я вижу в консоли, что состояние меняется

введите здесь описание изображения

прикрепленный компонент формы

import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';
import FieldFormControl from '../../common/FieldFormControl';

import {
    FormGroup,
    FormControl,
    ControlLabel,
    Button

} from 'react-bootstrap';

class ProfileForm extends Component {
    render() {
        const {handleSubmit, profile, pristine, reset, submitting} = this.props;

        return (
            <form onSubmit={handleSubmit}>
                <FormGroup controlId="signup-name">
                    <Field type="text" name="firsname" placeholder="test" value component={FieldFormControl}>Vorname</Field>
                </FormGroup>
                <FormGroup controlId="signup-username">
                    <Field type="text" name="lastname" placeholder={profile.username} value={profile.username} component={FieldFormControl}>Name</Field>
                </FormGroup>
                <FormGroup controlId="signup-email">
                    <Field type="text" name="email" placeholder={profile.username} value={profile.username} component={FieldFormControl}>Vorname</Field>
                </FormGroup>

                <Button
                    bsStyle="primary"
                    type="submit"
                    //disabled={pristine || submitting}
                    block
                >Speichern</Button>
            </form>
        );
    }
}

// Decorate the form component
ProfileForm = reduxForm({
    form: 'profileForm' // a unique name for this form
})(ProfileForm);

export default ProfileForm;

переопределение начальной загрузки для совместимости с редукционной формой

import React, { Component } from 'react';
import {FormGroup, FormControl, ControlLabel} from 'react-bootstrap';

export default class FieldFormControl extends Component {

    render () {

        const { placeholder, type, input, meta} = this.props;

        return (
            <FormGroup controlId={input.name} validationState={meta.error ? 'error' : 'success'}>
                <ControlLabel>{this.props.children}</ControlLabel>
                <FormControl type={type} placeholder={placeholder} value={input.value} onChange={input.onChange} />
                <FormControl.Feedback />
            </FormGroup>
        );
    }
}

person fefe    schedule 26.02.2017    source источник


Ответы (2)


Удалите опору value из ваших компонентов Field, redux-form обрабатывает обновление значения и передает его component, который вы передаете. Я предполагаю, что идея состоит в том, чтобы предоставить начальное значение, но это не место для этого.

<Field type="text" name="email" placeholder={profile.username} component={FieldFormControl}>Vorname</Field>

Вы также можете передать все реквизиты input вашему FormControl в свой FieldFormControl, чтобы получить onFocus, onBlur и т. д., все из которых предоставляет редукс-форма.

<FormControl placeholder={placeholder} {...input} />

Если вы хотите инициализировать поля значениями, используйте initialValues при подключении с использованием reduxForm или initialize, если это должно произойти после монтирования формы.

И, наконец, вы используете combineReducers дважды таким образом, что большинство ваших редукторов вложены не так, как вы предполагали. Чтобы упростить это, я бы импортировал routerReducer в ваш файл reducers/index.js и добавил его в ваш combineReducers.

const rootReducer = combineReducers({
    // short hand property names
    session,
    profile,
    map,
    form: formReducer,
    routing: routerReducer,
});

Тогда в вашем магазине у вас будет просто

const store = createStore(
    reducers,
    applyMiddleware(...middleware),
);

Затем вы должны увидеть, что у вас будут все ваши ключи в вашем состоянии (сеанс, профиль, форма, маршрутизация и т. д.), а не только по умолчанию и маршрутизация.

person Andy_D    schedule 26.02.2017
comment
Спасибо за отзыв и за подсказку! Я вносил исправления, но даже так я все еще не могу вводить значения внутри полей формы. Более того, я взял простую примерную форму с сайта документации redux-form и не работает в моем случае. Так что, очевидно, я делаю что-то не так - person fefe; 27.02.2017
comment
Ваша форма внутри редукса Provider? - person Andy_D; 27.02.2017
comment
да render( <Provider store={store}> <Router history={history} routes={routes} /> </Provider>, target ); - person fefe; 27.02.2017
comment
Хорошо, я вижу это. Ваш rootReducer не добавляется в ваш магазин правильно, поэтому у вас нет правильных ключей в вашем объекте состояния. Обновление ответа. - person Andy_D; 28.02.2017

Я не думаю, что это проблема редукционной формы.

Вместо этого я думаю, что ваше приложение слушает onChange вашего ввода и отправляет действие на избыточность. Итак, это основная причина: вы отправляете действие onChange, вызывая обновление состояния редукции (я думаю, что ваш код не изменил его в редюсере), и после этого редукс очищает пользовательский интерфейс рендеринга.

Чтобы исправить это, вы: обычно, когда вы отправляете действие onChange в вашем редукторе, явно обновляете свое состояние редукции. тогда новое состояние автоматически очистит ваш пользовательский интерфейс.

например ваш редуктор должен иметь подобное:

function myReducer(state = initialState, action) {
  switch (action.type) {
    case MY_INPUT_VALUE_CHANGE:
      return Object.assign({}, state, {
        vornname: action.data
      })
    default:
      return state
  }
}
person Xin    schedule 26.02.2017
comment
спасибо за отзыв! Где и как обновить состояние? - person fefe; 26.02.2017
comment
эй, это способ работы редукса: redux.js.org/docs/basics/Reducers. html я обновил код примера ответа - person Xin; 26.02.2017
comment
спасибо, у меня есть идея, просто я не могу понять, как мне работать с асинхронными данными. В качестве промежуточного ПО использую thunk, а исходные данные получаю через ajax. Теперь, как я могу отправлять действия формы, немного неясно, так как я изучаю эти вещи. - person fefe; 26.02.2017
comment
Предоставленный редюсер, который вы правильно используете, обрабатывает обновление состояния for для вас, как вы можете видеть в своем журнале действий. Вы знакомы с редукционной формой @Xin? Использование его редуктора для обработки состояния формы для вас является обычным использованием. @fefe проблема может быть в component, который вы используете со своими Field компонентами. Пожалуйста, покажите компонент формы. - person Andy_D; 26.02.2017
comment
Я прикреплю компонент, это переопределение, которое можно использовать с начальной загрузкой - person fefe; 26.02.2017