redux-form 无法在字段中键入值

redux-form unable to type values in fields

我无法使用 redux-form 在输入字段中键入值。我有以下减速机

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;

bootstrap 覆盖以与 redux-form 兼容

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>
        );
    }
}

我认为这不是 redux-form 的问题。

相反,我认为您的应用程序会监听您输入的 onChange,并将操作分派给 redux。所以这是根本原因:你调度 onChange 动作,导致 redux 状态更新,(我认为你的代码没有在 reducer 中改变它)然后,redux 刷新渲染 UI.

要修复它,您: 通常,当您分派 onChange 操作时,在您的 reducer 中,显式更新您或 redux 状态。然后新状态将自动刷新您的UI。

例如你的减速器应该像这样:

function myReducer(state = initialState, action) {
  switch (action.type) {
    case MY_INPUT_VALUE_CHANGE:
      return Object.assign({}, state, {
        vornname: action.data
      })
    default:
      return state
  }
}

从您的 Field 组件中删除 value 道具,redux-form 处理更新值并将其传递给您传递它的 component。我假设这里的想法是提供 initial 值,但这不是这样做的地方。

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

您还可以将所有 input 道具传递给 FieldFormControl 中的 FormControl,这样您就可以获得 onFocusonBlur 等,所有由 redux-form 提供。

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

如果你想用值初始化字段,如果它需要在表单安装后发生,请使用 initialValues when you connect using reduxForm, or initialize

最后,您使用了 combineReducers 两次,大多数 reducer 都以您不希望的方式嵌套。为了简化这一点,我会在您的 reducers/index.js 文件中导入 routerReducer,然后将其添加到您的 combineReducers 中。

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

然后,在您的商店中,您将只有

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

然后您应该会看到所有密钥都在您的状态(会话、配置文件、表单、路由等)中,而不仅仅是默认和路由。