ReactJS Redux Live编辑

时间:2016-06-28 09:51:35

标签: javascript postgresql reactjs redux

我正在尝试构建类似于React Redux Universal Hot Example的Widget示例的代码。唯一的例外是从PostgreSQL数据库中获取数据。

代码按原样列出组,但是当我点击编辑时,我会收到以下错误。

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `AdminGroupList`
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of `AdminGroupList`

这是我的AdminGroupList.js

import React, { Component } from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import { asyncConnect } from 'redux-async-connect';
import { routeActions } from 'react-router-redux';
// import { Table } from 'react-bootstrap/lib';
import * as groupActions from 'redux/modules/groups';
import {isLoaded, load as loadGroups} from 'redux/modules/groups';
import {initializeWithKey} from 'redux-form';
import { GroupForm } from 'components/Admin/GroupForm';

@asyncConnect([{
  deferred: true,
  promise: ({store: {dispatch, getState}}) => {
    if (!isLoaded(getState())) {
      return dispatch(loadGroups());
    }
  }
}])
@connect(
  state => ({
    groups: state.groups.data,
    editing: state.groups.editing,
    error: state.groups.error,
    loading: state.groups.loading
  }),
  { ...groupActions, initializeWithKey, pushState: routeActions.push })
export default class AdminGroupList extends Component {
  static propTypes = {
    groups: React.PropTypes.object,
    pushState: React.PropTypes.func.isRequired,
    error: React.PropTypes.string,
    loading: React.PropTypes.bool,
    initializeWithKey: React.PropTypes.func.isRequired,
    editing: React.PropTypes.object.isRequired,
    load: React.PropTypes.func.isRequired,
    editStart: React.PropTypes.func.isRequired
  }

  render() {
    const groups = Object.values(this.props.groups);
    const handleEdit = (group) => {
      const {editStart} = this.props;
      return () => editStart(String(group.id));
    };
    const { error, editing, loading, load} = this.props;
    let refreshClassName = 'fa fa-refresh';
    if (loading) {
      refreshClassName += ' fa-spin';
    }
    return (
      <div className="container">
        <h1>
          Tuoteryhmät ({groups.length})
          <button className="btn btn-success" onClick={load}>
            {' '} Reload Groups
          </button>
        </h1>
        <Helmet title="Groups"/>
        {error &&
        <div className="alert alert-danger" role="alert">
          <span className="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
          {' '}
          {error}
        </div>}
        {groups && groups.length &&
        <table className="table table-striped">
          <thead>
          <tr>
            <th>ID</th>
            <th>Name</th>
            <th></th>
          </tr>
          </thead>
          <tbody>
          {
            groups.map((group) => editing[group.id] ?
              <GroupForm formKey={String(group.id)} key={String(group.id)} initialValues={group}/> :
              <tr key={group.id}>
                <td>{group.id}</td>
                <td>{group.name}</td>
                <td>
                  <button className="btn btn-primary" onClick={handleEdit(group)}>
                    <i className="fa fa-pencil"/> Edit
                  </button>
                </td>
              </tr>)
          }
          </tbody>
        </table>}
      </div>
    );
  }
}

这是GroupForm.js

import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {reduxForm} from 'redux-form';
import groupValidation from 'utils/GroupValidation';
import * as groupActions from 'redux/modules/groups';

@connect(
  state => ({
    saveError: state.groups.saveError
  }),
  dispatch => bindActionCreators(groupActions, dispatch)
)
@reduxForm({
  form: 'group',
  fields: ['id', 'name'],
  validate: groupValidation
})
export default class GroupForm extends Component {
  static propTypes = {
    fields: PropTypes.object.isRequired,
    editStop: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    invalid: PropTypes.bool.isRequired,
    pristine: PropTypes.bool.isRequired,
    save: PropTypes.func.isRequired,
    submitting: PropTypes.bool.isRequired,
    saveError: PropTypes.object,
    formKey: PropTypes.string.isRequired,
    values: PropTypes.object.isRequired
  };

  render() {
    const { editStop, fields: {id, name}, formKey, handleSubmit, invalid,
      pristine, save, submitting, saveError: { [formKey]: saveError }, values } = this.props;
    return (
      <tr>
        <td>{id.value}</td>
        <td>
          <input type="text" className="form-control" {...name}/>
          {name.error && name.touched && <div className="text-danger">{name.error}</div>}
        </td>
        <td>
          <button className="btn btn-default"
                  onClick={() => editStop(formKey)}
                  disabled={submitting}>
            <i className="fa fa-ban"/> Cancel
          </button>
          <button className="btn btn-success"
                  onClick={handleSubmit(() => save(values)
                    .then(result => {
                      if (result && typeof result.error === 'object') {
                        return Promise.reject(result.error);
                      }
                    })
                  )}
                  disabled={pristine || invalid || submitting}>
            <i className={'fa ' + (submitting ? 'fa-cog fa-spin' : 'fa-cloud')}/> Tallenna
          </button>
          {saveError && <div className="text-danger">{saveError}</div>}
        </td>
      </tr>
    );
  }
}

1 个答案:

答案 0 :(得分:2)

此错误消息表示您的导入存在问题。

如果您使用GroupForm默认导出导出default class GroupForm,则应在AdminGroupList.js中导出它而不使用大括号:

将此行import { GroupForm } from 'components/Admin/GroupForm'改为import GroupForm from 'components/Admin/GroupForm'