【问题标题】:Warning: Failed prop type: The prop `exercise` is marked as required in `EditExercise`, but its value is `undefined`警告:失败的道具类型:道具`exercise`在`EditExercise`中标记为必需,但其值为`undefined`
【发布时间】:2020-12-24 12:40:23
【问题描述】:

我正在尝试从 MongoDB 获取单个对象。我成功地获得了整个数据库。 当我 console.log() 减少器中的有效负载时,它显示一个对象而不是数组,以及我想要的正确对象。 我不明白为什么没有将对象发送到组件,因为我在不同的组件中执行完全相同的过程。

来自动作文件:exerciseActions.js:

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您可能会找到原因here。您应该使用 componentDidMount。

    在 componentWillMount() 中使用 fetch 调用会导致组件首先呈现空数据,因为 componentWillMount() 不会在组件第一次呈现之前返回。

    由于 JavaScript 事件是异步的,当您进行 API 调用时,浏览器会在调用仍在进行时继续执行其他工作。使用 React,当组件渲染时,它不会等待 componentWillMount() 完成,因此组件会继续渲染。

    case GET_BY_ID:
        console.log(action.payload);
        return {
            ...state, // Btw, you forgot this line
            exercise: action.payload
        }
    

    【讨论】:

    • 感谢您的输入,从现在开始我将使用 componentDidMount。但它并没有解决错误
    • 它可能找不到运动。您可能会忘记减速器的名称。 const mapStateToProps = state => ({ exercise: state.exercise, // 应该是 state.[reducerName].exercise })
    猜你喜欢
    • 1970-01-01
    • 2022-07-20
    • 2018-03-12
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 2020-01-26
    • 2021-09-28
    • 1970-01-01
    相关资源
    最近更新 更多