Javascript 警告:失败的道具类型:道具'exercise'在'EditExercise'中标记为必需,但其值为'undefined'`
我正在尝试从MongoDB获取一个对象。我成功地得到了整个数据库。 当我在console.log()中读取reducer中的有效负载时,它显示的是单个对象而不是数组,以及我想要的正确对象。 我无法理解为什么不将对象发送到组件,因为我在不同的组件中执行完全相同的过程 从操作文件:exerciseActions.js:Javascript 警告:失败的道具类型:道具'exercise'在'EditExercise'中标记为必需,但其值为'undefined'`,javascript,reactjs,Javascript,Reactjs,我正在尝试从MongoDB获取一个对象。我成功地得到了整个数据库。 当我在console.log()中读取reducer中的有效负载时,它显示的是单个对象而不是数组,以及我想要的正确对象。 我无法理解为什么不将对象发送到组件,因为我在不同的组件中执行完全相同的过程 从操作文件:exerciseActions.js: export const getExerciseByID = (exerciseID) => dispatch => { fetch('http://localh
export const getExerciseByID = (exerciseID) => dispatch => {
fetch('http://localhost:5000/exercises/' + exerciseID)
.then(res => res.json())
.then(exercise => dispatch({
type: GET_BY_ID,
payload: exercise
}))
}
减速器:
import { FETCH_EXERCISES, NEW_EXERCISE, EXERCISE_REMOVE, GET_BY_ID } from '../actions/types'
const initialState = {
exercises: [],
exercise: {}
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_EXERCISES:
return {
...state,
exercises: action.payload
};
case NEW_EXERCISE:
return {
...state,
exercise: action.payload
};
case EXERCISE_REMOVE:
return {
...state,
exercises: state.exercises.filter(exercises => exercises._id !== action.exercises._Id)
};
case GET_BY_ID:
console.log(action.payload);
return {
exercise: action.payload
}
default: return state;
}
}
反应组分:
import React, { Component } from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { getExerciseByID } from '../actions/exerciseActions'
class EditExercise extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeDescription = this.onChangeDescription.bind(this);
this.onChangeDuration = this.onChangeDuration.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
exercise: null,
users: []
}
}
componentWillMount() {
const exercise = this.props.getExerciseByID(this.props.match.params.id);
console.log(exercise);
}
render() {
const exercise = this.props.exercise
return (
<div>
<p>{exercise}
</p>
<h3>Edit Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}>
{
this.state.users.map(function (user) {
return <option
key={user}
value={user}>{user}
</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={this.state.description}
onChange={this.onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input
type="text"
className="form-control"
value={this.state.duration}
onChange={this.onChangeDuration}
/>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
selected={this.state.date}
onChange={this.onChangeDate}
/>
</div>
</div>
<div className="form-group">
<input type="submit" value="Edit Exercise Log" className="btn btn-primary" />
</div>
</form>
</div>
)
}
}
EditExercise.propTypes = {
getExerciseByID: PropTypes.func.isRequired,
exercise: PropTypes.array.isRequired,
}
const mapStateToProps = state => ({
exercise: state.exercise,
})
export default connect(mapStateToProps, { getExerciseByID })(EditExercise);
import React,{Component}来自'React';
从“axios”导入axios;
从“react DatePicker”导入日期选择器;
导入“react datepicker/dist/react datepicker.css”;
从“道具类型”导入道具类型
从“react redux”导入{connect}
从“../actions/exerciseActions”导入{getExerciseByID}
类扩展组件{
建造师(道具){
超级(道具);
this.onChangeUsername=this.onChangeUsername.bind(this);
this.onchangescription=this.onchangescription.bind(this);
this.onChangeDuration=this.onChangeDuration.bind(this);
this.onChangeDate=this.onChangeDate.bind(this);
this.onSubmit=this.onSubmit.bind(this);
此.state={
练习:空,
用户:[]
}
}
组件willmount(){
const exercise=this.props.getExerciseByID(this.props.match.params.id);
控制台日志(练习);
}
render(){
const exercise=this.props.exercise
返回(
{练习}
编辑练习日志
用户名:
{
this.state.users.map(函数(用户){
返回{user}
;
})
}
说明:
持续时间(分钟):
日期:
)
}
}
EditExecution.propTypes={
getExerciseByID:PropTypes.func.isRequired,
练习:需要PropTypes.array.isRequired,
}
常量mapStateToProps=状态=>({
演习:国家演习,
})
导出默认连接(mapStateToProps,{getExerciseByID})(EditExercise);
您可能会找到原因。您应该使用componentDidMount
在componentWillMount()中使用fetch调用会导致组件首先呈现空数据,因为componentWillMount()在组件第一次呈现之前不会返回
由于JavaScript事件是异步的,因此当您进行API调用时,浏览器会在调用仍在运行时继续执行其他工作。使用React,组件渲染时不会等待componentWillMount()完成,因此组件将继续渲染
感谢您的输入,从现在起我将使用componentDidMount。但它并没有解决可能找不到锻炼的错误。您可能会忘记减速器的名称。const-mapStateToProps=state=>({exercise:state.exercise,//它应该是state。[reducerName].exercise})
case GET_BY_ID:
console.log(action.payload);
return {
...state, // Btw, you forgot this line
exercise: action.payload
}