首页 > 解决方案 > React-Redux - 调用操作时出现 TypeError: String.prototype.property called on null or undefined

问题描述

我正在尝试实现 Redux 来动态控制我的导航栏链接。我在导航栏链接上有一个“链接活动”功能,该功能根据显示的页面而处于活动状态。通过我在应用程序中访问不同页面的所有链接,使用 Redux 商店处理哪些导航链接处于活动状态似乎更容易。

我收到此错误:TypeError: String.prototype.link called on null or undefined当我调用我的一项操作时,更新商店的链接应该处于活动状态。

这是我的实施,从我的行动开始:

navbar_actions.js

const Types = {
  NAV_LINK_ACTIVE: 'NAV_LINK_ACTIVE',
};

const navlinkActive = (link) => ({
  type: Types.NAV_LINK_ACTIVE,
  payload: link,
});

export default {
  navlinkActive,
  Types,
};

navbar_reducers.js

import NAVBAR_ACTIONS from '../actions/navbar_actions';
import _ from 'lodash';

const defaultState = {
  link: '',
};

const navbarReducer = (state = defaultState, action) => {
  switch (action.type) {
    case NAVBAR_ACTIONS.Types.NAV_LINK_ACTIVE: {
      let link = action.payload;
      return link;
    }
    default:
      return state;
  }
};

export default navbarReducer;

商店.js

import { createStore } from 'redux';

import navbarReducer from '../reducers/navbar_reducers';

export default function configureStore(initialState) {
  const store = createStore(navbarReducer, initialState);
  return store;
}

这是导航栏用来呈现链接的我的链接组件(该组件只需要访问存储状态):

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';

//Redux

import NAVBAR_ACTIONS from '../../../../modules/actions/navbar_actions';
import { connect } from 'react-redux';

import propTypes from 'prop-types';

//Styles
import { LinkContainer, LinkWrap } from './styles';

//Notes
//@Required: links array passed as props. Each object in the links array should contain a path and name property. Refer to propTypes definition at the bottom.

const Links = (props) => {
  const [clickedLink, setClickedLink] = useState('Home');
  useEffect(() => {
    if (props.link.length === 0) return;
    else setClickedLink(props.link);
  }, [props.link]);
  return (
    <LinkContainer>
      {props.links.map((link, i) => (
        <LinkWrap isActive={link.name === clickedLink ? true : false} key={i}>
          <Link
            to={link.path}
            onClick={() => {
              setClickedLink(link.name);
            }}
          >
            {link.name}
          </Link>
        </LinkWrap>
      ))}
    </LinkContainer>
  );
};

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

export default connect(mapStateToProps, null)(Links);

Links.propTypes = {
  links: propTypes.arrayOf(
    propTypes.shape({
      path: propTypes.string.isRequired,
      name: propTypes.string.isRequired,
    })
  ).isRequired,
};

通过useEffect()钩子,任何时候props.link更新,它都会在Links组件状态中更新。这就是我认为store每次更改时我都会从状态中获取更新链接的方式。可能是错的,但这是我的尝试。

这是我在其中调用操作的组件:

import React from 'react';

//Redux
import { connect } from 'react-redux';
import NAVBAR_ACTIONS from '../../../modules/actions/navbar_actions';

import { Link } from 'react-router-dom';

//Styles
import {
  HomePageHero,
  LatestPostsHeader,
  HeroHeader,
  HeroText,
  HeroViewPosts,
} from './styles';

//Components
import Page from '../../Layout/Page';
import Blog from '../Blog/Blog';
import SocialLinks from './Components/SocialMediaLinks/SocialLinks';

const Home = (props) => {
  console.log(props);
  return (
    <Page noheader={true} pageTitle="">
      <HomePageHero>
        <HeroHeader>
          <p>Maison</p>
          <div></div>
          <p>Moa</p>
        </HeroHeader>
        <HeroText>
          <p>
            Loreum Ipsum 
          </p>
        </HeroText>
        <HeroViewPosts>
          <Link
            to="/blog"
            onClick={() => {
              props.navlinkActive('blog');
              console.log(props);
            }}
          >
            View My Blog
          </Link>
        </HeroViewPosts>
        <SocialLinks />
      </HomePageHero>
      <LatestPostsHeader>
        <h3>Latest Posts</h3>
      </LatestPostsHeader>
      <Blog pageTitle="Latest Posts" noheader={true} />
    </Page>
  );
};

const mapDispatchToProps = (dispatch) => ({
  navlinkActive: (link) => dispatch(NAVBAR_ACTIONS.navlinkActive(link)),
});

export default connect(null, mapDispatchToProps)(Home);

这是我在调用时遇到的错误的实际屏幕截图props.navlinkActive()

在此处输入图像描述

我对这个错误有点不知所措,因为我真的找不到任何关于它的“Redux”。提前感谢您的帮助和洞察力!

标签: javascriptreactjsredux

解决方案


最终解决了这个问题。错误来自我的Links.js组件:

特别是这里:

  useEffect(() => {
    if (props.link.length === 0) return;
    else setClickedLink(props.link);
  }, [props.link]);

props.link未定义。这是因为我没有从navbar_reducer.js.

这就是减速器应该如何返回状态(cloneDeep()在此处使用 lodash):

const navbarReducer = (state = defaultState, action) => {
  switch (action.type) {
    case NAVBAR_ACTIONS.Types.NAV_LINK_ACTIVE: {
      let link = action.payload;
      let newState = _.cloneDeep(state);
      newState.link = link;
      return newState;
    }
    default:
      return state;
  }
};

老办法。我正在修改 reducer 中的现有状态,而不是返回具有必要更改的新状态副本。我直接改变了现有状态,这样做时,Redux 不会检测到更改,因此任何connect()用于访问存储的组件都不会得到更新。

现在一切都按预期工作。这是 React 中的第一条规则。不要改变状态!我应该知道的。确保您始终获得状态的深层副本,然后对该副本进行更改。


推荐阅读