Reputation: 157
I'm trying to build a similar code like the Widget example from React Redux Universal Hot Example. The only exception is that the data is fetched from PostgreSQL database.
The code lists the groups as it should, but when I click on Edit I get the following errors.
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`
Here is my 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>
);
}
}
And here is 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>
);
}
}
Upvotes: 0
Views: 375
Reputation: 1062
This error message means you have an issue with your imports.
If you export export GroupForm
by default with default class GroupForm
, you should import it without the curly brackets in AdminGroupList.js:
Replace this line import { GroupForm } from 'components/Admin/GroupForm'
by import GroupForm from 'components/Admin/GroupForm'
Upvotes: 2