无法解构“未定义”或“空”的属性“用户”

IT技术 javascript reactjs mongodb redux
2021-05-26 04:43:24

使用 redux 检索用户信息时出错。我想从数据库中获取用户信息(名称、密码和头像的地址),然后对其进行编辑。

我正在使用 nodejs、express、react、redux 和 jwt。

Actions/user.js
import axios from 'axios';
import {setAlert} from './alert';

import {GET_USER, USER_ERROR} from './types';

//Get current users profile
export const getCurrentUser = () => async dispatch => {
    try {
        const res = await axios.get('/api/users/me');

        dispatch({
            type: GET_USER,
            payload: res.data
        });
    } catch (err) {
        dispatch({
            type:USER_ERROR,
            payload:{msg: err.response.statusText, status: err.response.status}
        });
    }
};

Reducers/user.js
import {GET_USER, USER_ERROR, CLEAR_USER} from '../actions/types';

const initialState = {
    user: null,
    users: [],
    loading: true,
    error: {}
}

export default function(state = initialState, action) {
    const {type, payload} = action;
    switch(type){
        case GET_USER:
        return{
            ...state,
            loading:false,
            user:payload
        };
        case USER_ERROR:
            return{
            ...state,
            error:payload,
            loading: false
        };
        default:
            return state;
    }
}

Components/edituser/EditUser.js
import React, {useState, Fragment, useEffect} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {getCurrentUser} from '../../actions/user';
import {Link, withRouter} from 'react-router-dom';
import Alert from '../layout/Alert';
import InputSelector from '../util/InputSelector';

const EditUser = ({
    user:{user,loading}, 
    getCurrentUser, 
    history}) => {
    const [formData, setFormData] = useState({
        name: '',
        email: '',
        password: ''
    });

    useEffect(()=>{
        getCurrentUser();
    });
    return (
        <Fragment>
      <div className="col-md-12 mb-3">
                <div className="card">
                    <div className="card-body">
                        <div className="row">
                            <div className="col-md-3 d-flex align-items-center">
                            <div className="img">
                            <img className="img-fluid" src={'/uploads/noImg.jpg'} />
                        </div>
                            </div>
                        <div className="col-md-9">
                        <form>
                            <div className="form-group">
                                <label><i className="fas fa-user"></i> Username</label>
                                <input 
                                type="text" 
                                name="skills"
                                className="form-control" 
                                placeholder="Edita tu nombre de usuario"
                                />
                            </div>
                            <div className="form-group">
                                <label><i className="fas fa-envelope"></i> Email</label>
                                <input 
                                type="text" 
                                name="skills"
                                className="form-control" 
                                placeholder="Edita tu email"
                                />
                            </div>
                            <div className="form-group">
                                <label><i className="fas fa-key"></i> Contraseña</label>
                                <input 
                                type="text" 
                                name="skills"
                                className="form-control" 
                                placeholder="Edita tu nombre de contraseña"
                                />
                            </div>
                            <div className="form-group" >
                            <label><i class="fas fa-upload"></i> Imagen De Perfil</label>
                        <InputSelector/>
                        </div>
                        <div className="col-md-12 text-center">
                        <button className="btn btn-primary btn-block"><i class="fas fa-check"></i> Guardar</button>
                        </div>
                        </form> 
                        </div>
                        </div>
                    </div>
                </div>
            </div>
            </Fragment>
    );
};
EditUser.propTypes = {
    getCurrentUser: PropTypes.func.isRequired,
    user: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
        user: state.user
     });

export default connect(mapStateToProps, {getCurrentUser}) 
(withRouter(EditUser));

https://imgur.com/xLzAu1A

当我编写 user: {user, loading} 时,问题总是发生,当我放置另一个我已经完成的代码时,它可以正常工作,但是每当我编写页面失败时。

2个回答

cannot destructure property user of 'undefined' or 'null'. 这意味着user data null or undefined在您第一次使用从服务器获取数据时。对服务器的 API 调用是异步的。第二次,你会得到user data

我看到您作为 redux props的用户res.data来自服务器。我不确定结构是res.data什么?所以在组件中,你应该这样做:

const EditUser = ({
    user, 
    getCurrentUser, 
    history
}) => {
    if (user) {
        const { loading, ... } = user // Get another key in user object
    }
...
...
...
// When you try to destructure action object by default for the first time it would not have contain any keys defined by us, However it would contain default keys that redux provides. While Destructring this object would result in undefined or null because there is no matching key. So destructure inside the condition where it matches.
export const addBug = desc => ({
    type: actions.BUG_ADDED,
    payload: {
      description: desc
    }
  });
// i am dispatching the action in the below line
 store.dispatch(addBug('button is not clickable'));

// below i have destructred the action.payload object

let lastId = 0;
function reducer(state = [], action) {
    console.log(action);       
    switch(action.type) {
        case actions.BUG_ADDED:
            const {description} = action.payload;
            return [
              ...state,
              {
                id: ++lastId,
                description,
                resolved: false,
              },
            ];

            case actions.BUG_REMOVED:
                return state.filter(bug => action.payload.id !== bug.id);

            default: return state;
    }
}

export default reducer;