因此,今天下午我啓動了我用React前端製作的論文,一個Laravel後端。運行我的React dev服務器時出現的錯誤如下:未捕獲的錯誤:元素類型無效:預期爲字符串(對於內置組件)或類/函數(對於複合組件),但得到:未定義。你可能忘了您的組件從它的定義文件導出。反應:元素類型無效:期望一個字符串(對於內置組件)或一個類/函數(對於複合組件),但得到:undefined
現在,這是一個相當龐大的項目,所以我來這裏的問題可能是很笨,經過一番研究,我真的來了在一些路由可能是問題,但我沒有嘗試解決這個問題。
我index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { Router, Route, browserHistory } from 'react-router';
import reducer from './reducers';
import App from './components/App';
import SignIn from './components/SignIn';
import SignUp from './components/SignUp';
import BoardView from './components/BoardView';
import ProjectView from './components/ProjectView';
import SprintView from './components/SprintView';
import ListView from './components/ListView';
import SprintChart from './components/Chart';
const store = createStore(reducer);
function requireAuthentication(nextState, replace) {
if(!isUserAuthenticated() || !checkNewProjectStorage()) {
console.log('nextstate', nextState);
replace({
pathname: '/signin',
state: { nextPathname: nextState.location.pathname }
})
}
}
function isUserAuthenticated() {
var authenticated = false;
if(localStorage.getItem('token')) {
authenticated = true;
}
return authenticated;
}
function checkNewProjectStorage() {
var userIdStored = false;
if(localStorage.getItem('userId')) {
userIdStored = true;
}
return userIdStored;
}
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={App} onEnter={requireAuthentication.bind(this)} />
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
<Route path="/sprints" onEnter={requireAuthentication.bind(this)} component={SprintView} />
<Route path="/chart" onEnter={requireAuthentication.bind(this)} component={SprintChart} />
<Route path="/board" onEnter={requireAuthentication.bind(this)} component={BoardView} />
<Route path="/list" onEnter={requireAuthentication.bind(this)} component={ListView} />
</Router>
</Provider>,
document.getElementById('root')
)
我App.jsx:
import React, { Component } from 'react';
import { browserHistory } from 'react-router';
import { Dropdown, Button, NavItem, Col, Card } from 'react-materialize';
import logo from '../images/scrumtastic_logo_white.png';
import axios from 'axios';
import { BASE_URL } from '../constants';
import Toast from './Toast'
import '../App.css';
import ReactConfirmAlert, { confirmAlert } from 'react-confirm-alert';
import 'react-confirm-alert/src/react-confirm-alert.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
'userId': '',
'email': '',
'token': '',
'projects': [],
'projectId': '',
'editingMode': false,
'name': null,
'newName': '',
'description': null,
'newDesc': '',
'showEditingMode': -1,
'clickedProject': null,
'error': [],
'newProjectBool': false
}
}
componentWillMount() {
let email = localStorage.getItem('email');
let token = localStorage.getItem('token');
let userId = localStorage.getItem('userId');
this.setState({'email': email, 'token': token, 'userId': userId});
}
componentDidMount() {
const token = 'Bearer ' + this.state.token
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['Authorization'] = token
axios.get(BASE_URL + '/users/' + this.state.userId + '/projects')
.then((data) => {
let userProjects = [];
data.data[0].projects.forEach((project) => {
userProjects.push(project);
})
this.setState({'projects': userProjects});
})
.catch((error) => {
this.setState({error});
})
}
renderErrors() {
let errors = [];
if(this.state.error.response && this.state.error.response.data.error)
{
let errorArray = this.state.error.response.data.error;
let i = 0;
for(var key in errorArray) {
if(errorArray.hasOwnProperty(key)) {
errors.push(<p className="errorMessage" key={"error_" + i}>{errorArray[key][0]}</p>);
}
i++;
}
}
return <div className="center-align-error">{errors}</div>
}
logOut() {
const token = 'Bearer ' + this.state.token
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['Authorization'] = token
axios.post(`${BASE_URL}/logout`, {
'email': this.state.email,
})
.then((data) => {
if(data.status === 200) {
localStorage.removeItem('token')
localStorage.removeItem('email')
let t = new Toast("Succesfully logged out!", 2500)
t.Render();
setTimeout(() => {browserHistory.push('/signin')}, 2500)
}
})
.catch((error) => {
this.setState({error});
})
}
renderProjects() {
const projects = this.state.projects;
return (
<ul>
{
projects.map((project) => {
return (
<Col key={project.id} m={6} s={12}>
{(!this.state.editingMode && (this.state.clickedProject === null)) || (!this.state.editingMode && (this.state.clickedProject === project.id)) || (!this.state.editingMode && (this.state.clickedProject !== project.id)) || (this.state.editingMode && (this.state.clickedProject !== project.id)) ? <Card key={project.id} style={{backgroundColor: '#fff'}} textClassName="grey-text text-darken-4" title={project.name} actions={[<a style={{color: 'white', fontWeight: 'bold', cursor: 'pointer'}} key="Details Project" onClick={() => {this.projectView(project.id, project.name)}}>View Backlog</a>]}>
<p>{project.description}</p>
<a key="Delete Project" onClick={() => {this.confirm(project.id)}} style={{cursor: 'pointer'}}><i className="material-icons small" style={{color: '#a6262c', float: 'right'}}>delete_forever</i></a>
<a key="Edit Project" onClick={() => {this.editProject(project.id, project.name, project.description)}} style={{cursor: 'pointer'}}><i className="material-icons small" style={{color: '#2633a6', float: 'right'}}>mode_edit</i></a>
</Card> :
<Card key={project.id} style={{backgroundColor: '#fff', height: '280px'}} textClassName="grey-text text-darken-4">
<form className="col s8">
<div className="row">
<div className="input-field col s12">
<input
className="validate"
id="name"
type="text"
onChange={event => this.setState({name:event.target.value})}
/>
<label htmlFor="name"><b>Name:</b> {project.name}</label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<textarea
className="materialize-textarea"
id="description"
type="text"
onChange={event => this.setState({description:event.target.value})}
/>
<label htmlFor="description"><b>Description:</b> {project.description}</label>
</div>
</div>
</form>
<a onClick={() => {this.editProject(project.id)}} style={{cursor: 'pointer'}}><i className="material-icons small" style={{color: '#2633a6', float: 'right'}}>mode_edit</i></a>
</Card>}
</Col>
)
})
}
</ul>
)
}
editProject(projectId, projectName, projectDescription) {
if(this.state.editingMode === true) {
const token = 'Bearer ' + this.state.token;
let newName = this.state.newName;
let newDesc = this.state.newDesc;
let projects = this.state.projects;
if(this.state.name) {
newName = this.state.name
}
if(this.state.description) {
newDesc = this.state.description
}
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['Authorization'] = token
axios.put(`${BASE_URL}/projects/${projectId}`, {
'name': newName,
'description': newDesc
})
.then((data) => {
for (var i=0; i < projects.length; i++) {
if (projects[i].id === projectId) {
projects[i].name = newName;
projects[i].description = newDesc;
this.setState({'projects': projects});
}
}
})
.catch((error) => {
this.setState({error});
})
}
else {
this.setState({'newName': projectName, 'newDesc': projectDescription});
}
if(projectId) {
this.setState({'clickedProject': projectId});
}
this.setState({'editingMode': !this.state.editingMode});
}
confirm(projectId) {
confirmAlert({
message: 'Are you sure you want to delete this project?',
confirmLabel: 'Delete',
cancelLabel: 'Cancel',
onConfirm:() => this.deleteProject(projectId)
})
}
deleteProject(projectId) {
const token = 'Bearer ' + this.state.token
let projects = this.state.projects;
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['Authorization'] = token
axios.delete(BASE_URL + '/projects/' + projectId)
.then((data) => {
this.searchAndDeleteProjectFromState(projectId, projects);
})
.catch((error) => {
this.setState({error});
})
}
searchAndDeleteProjectFromState(keyName, array) {
for (var i=0; i < array.length; i++) {
if (array[i].id === keyName) {
delete array[i]
this.setState({'projects': array});
let t = new Toast("Succesfully deleted project!", 2500)
t.Render();
}
}
}
projectView(projectId, projectName) {
localStorage.setItem('projectId', projectId);
localStorage.setItem('projectName', projectName);
browserHistory.push('/projects');
}
newProject() {
const token = 'Bearer ' + this.state.token
let projects = this.state.projects;
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.headers.common['Authorization'] = token
axios.post(`${BASE_URL}/projects`, {
'name': this.state.name,
'description': this.state.description,
'user_id': this.state.userId
})
.then((data) => {
projects.push(data.data);
this.setState({projects: projects});
this.setState({newProjectBool: false});
})
.catch((error) => {
this.setState({error});
})
}
setNewProjectBool() {
this.setState({newProjectBool: true})
}
renderNewProject() {
return (
<Col m={6} s={12}>
{ (!this.state.newProjectBool) ?
<Card key="New Project" style={{backgroundColor: '#fff'}} textClassName="grey-text text-darken-4" actions={[<a key="New Project" style={{cursor: 'pointer', color: 'white', fontWeight: 'bold'}} onClick={() => this.setNewProjectBool()}>+ Make new project</a>]}>
<div key="New Project" style={{fontSize: '20px'}}>[Your new project will appear here]</div>
</Card> :
<Card key="New Project" style={{backgroundColor: '#fff', height: '280px'}} textClassName="grey-text text-darken-4">
<form className="col s8">
<div className="row">
<div className="input-field col s12">
<input
className="validate"
id="name"
type="text"
onChange={event => this.setState({name:event.target.value})}
/>
<label htmlFor="name"><b>Project Name</b></label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<textarea
className="materialize-textarea"
id="description"
type="text"
onChange={event => this.setState({description:event.target.value})}
/>
<label htmlFor="description"><b>Project Description</b></label>
</div>
</div>
</form>
<a onClick={() => {this.newProject()}} style={{cursor: 'pointer'}}><i className="material-icons small" style={{color: '#2ca626', float: 'right'}}>add_box</i></a>
</Card>
}
</Col>
)
}
render() {
return (
<div>
<nav className="teal lighten-3">
<div className="nav-wrapper">
<a className="brand-logo" href="/"><img className="nav-logo" src={logo} alt="logo"/></a>
<ul id="nav-mobile" className="right hide-on-med-and-down" style={{marginRight: '10px'}}>
<i className="material-icons" style={{height: 'inherit', lineHeight: 'inherit', float: 'left', margin: '0 30px 0 0', width: '2px'}}>perm_identity</i>
<Dropdown trigger={
<Button style={{display: 'inline'}}>{this.state.email}</Button>
}>
<NavItem onClick={this.logOut.bind(this)}><i className="material-icons">input</i>Log Out</NavItem>
<NavItem divider />
</Dropdown>
</ul>
</div>
</nav>
<div className="row">
<div className="col s2"/>
<div className="col s8">
<h2 style={{color: '#26a69a'}}>Projects</h2>
{
this.renderProjects()
}
{this.renderNewProject()}
</div>
<div className="col s2"/>
</div>
<div className="row">
<div className="col s2" />
<div className="col s8">
{this.renderErrors()}
</div>
<div className="col s2" />
</div>
</div>
)
}
}
export default App;
如果你想辦理其他成分,我的項目託管在GitHub上:Dissertation Project
會如果有人能夠幫助我,那就意味着我的世界,因爲我需要在3天內做完演講。
你檢查了每個組件,看看你是否錯過了導入?它看起來像你可能正在使用一個組件,但忘記將它導入到某個文件中。你是否嘗試過使用Chrome的堆棧跟蹤來查看錯誤發生的位置? – Demon
通過所有組件,我一直無法找到一個未導入的組件,不知道如何使用鉻的堆棧跟蹤作爲錯誤來自節點模塊,所以不知道如何從那裏跟蹤 – Pjai1