Redux状态的嵌套对象可用,但在组件内不可访问

时间:2020-06-12 08:27:50

标签: reactjs redux react-redux

在此处输入代码我正在通过我的app.js文件中的提供者包装为整个React应用提供Redux全局状态。

除了“当前配置文件”之外,我没有任何其他状态可以访问。

这里是 组件

import React, { Fragment, useEffect } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";

import { loadTargetProfiles, loadCurrentProfile  } from "../../actions/profile";

const Friends = ({
  loadCurrentProfile,
  loadTargetProfiles,
  profile: { currentProfile, targetProfiles, targetProfilesAreLoading },
}) => {
  useEffect(() => {
    loadTargetProfiles();
    loadCurrentProfile();
  }, []);

  console.log(currentProfile);

  return (
     ...
};

Friends.propTypes = {
  loadTargetProfiles: PropTypes.func.isRequired,
  loadCurrentProfile: PropTypes.func.isRequired,
  profile: PropTypes.object.isRequired,
};

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

export default connect(mapStateToProps, {
  loadCurrentProfile,
  loadTargetProfiles,
})(Friends);

这是loadCurrentProfile 动作 ,负责提供currentProfile状态。

export const loadCurrentProfile = () => async (dispatch) => {
  try {
    const res = await api.get("/profile/current");

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

这是 减速器

的相关部分
const initialState = {
  currentProfile: null,
  targetProfile: null,
  targetProfiles: [],
  currentProfileIsLoading: true,
  targetProfileIsLoading: true,
  targetProfilesAreLoading: true,
  error: {},
};

//
// Export Reducer
export default function (state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case LOAD_CURRENT_PROFILE:
      return {
        ...state,
        currentProfile: payload,
        currentProfileIsLoading: false,
      };

这是受到攻击的 API

router.get("/current", auth, async (req, res) => {
  try {
    const profile = await Profile.findOne({
      user: req.user.id,
    }).populate("user", ["_id", "username", "registerdate"]);

    if (!profile) {
      return res
        .status(400)
        .json({ msg: "There is no profile for this user." });
    }

    res.json(profile);
  } catch (err) {
    console.error(err.message);
    res.status(500).send("Server Error...");
  }
});

这是 控制台

enter image description here

这是currentProfile状态的展开状态:

enter image description here

例如,当我尝试进入currentProfile状态时

  const Friends = ({
  loadCurrentProfile,
  loadTargetProfiles,
  profile: { currentProfile: {
    avatar
  }, targetProfiles, targetProfilesAreLoading },
}) => {
  useEffect(() => {
    loadTargetProfiles();
    loadCurrentProfile();
  }, []);

  console.log(avatar);

它给我错误:

TypeError:无法读取null的属性“头像”

这是Redux Dev Tools屏幕截图:

enter image description here

修复:

我(在声明函数后)通过访问内部状态(暂时)摆脱了错误。

const Friends= ({
  profile: { currentProfileIsLoading },
  currentProfile,
}) => {
  currentProfile && console.log(currentProfile.avatar);

,它现在可以使用,但肯定不是最优雅的解决方案。有没有一种方法可以在函数声明中添加此防护,以将状态设置在一个地方?

1 个答案:

答案 0 :(得分:3)

问题targetProfilestargetProfilesAreLoading在您的状态下均为真实值,但是currentProfile为空,直到GET解析。您无法访问空对象的avatar属性。

您可以为profile提供一些默认参数值,但这只有在profile未定义的情况下才有效,空值将作为已定义的值。

const Friends = ({
  loadCurrentProfile,
  loadTargetProfiles,
  profile: {
    currentProfile = {},
    targetProfiles,
    targetProfilesAreLoading
  },
}) => {
  useEffect(() => {
    loadTargetProfiles();
    loadCurrentProfile();
  }, []);

  console.log(currentProfile);

  return (
     ...
};

您还可以在可能未定义/空的对象上使用防护措施

currentProfile && currentProfile.avatar

另一种选择是使用状态选择器库(例如reselect),该状态选择器库允许您提取/增强/派生/等...作为道具传递的状态值。这还允许您设置状态的默认/后备值。它与redux很好地配对。