React 报告 props."function" 不是一个函数
P粉475315142
P粉475315142 2023-09-04 10:38:59
[React讨论组]

我正在创建我的第一个网上商店,但遇到了问题。我制作了假 API,其中包含产品卡数据,当我使用 axios.get 获取它们并添加到状态时,我发现“props.addCardData 不是函数”。我必须说,一切工作正常,直到我添加 axios.get 。其他函数我使用与函数 addCardData 相同的方式:我的意思是,我使用了 mapDispatchToProps,我使用了 props.addCardData - 我没有在 axios.get 或其他请求中使用它们)。我之前使用任何功能都没有问题。

我计划通过 axios.get 获取数据,从卡片容器调用一个函数,该函数将调用以操作创建者作为参数的调度。

我还发现“无法读取未定义的属性(读取“addCardData”)。

下面,我已经指出了受问题影响的代码部分(我已经指出了哪些代码适用于哪些元素)

这是 Cards 组件中的代码(我没有在此处添加导入,但 ofc 我拥有所有导入):

const Cards = (props) => {

  axios.get('https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e')
    .then(response => {
      props.addCardData(response.data)
    })

  let cardsArray = Object.keys(props.cardsData).map(card => (
    <OfferCard
      key={card.id}
      bg={props.cardsData[card].bg}
      id={props.cardsData[card].tagId}
      title={props.cardsData[card].title}
      text={props.cardsData[card].text}
      button={
        <Container fluid>
          <Row className={'row-cols-auto'}>
            {props.cardsData[card].button.map(button => (
              <CardsButton
                key={button.id}
                link={button.link}
                type={button.type}
                class={button.class}
                name={button.name}
              />
            ))}
          </Row>
        </Container>
      }
    />
  ))

  return (
    <Container fluid>
      <img src={'./backgrounds/bestoffers.png'} alt={'BEST OFFERS'} className={'img-fluid imgTab'} />
      <Row xs={1} md={2} id={'cards-row'} className={'border border-4 g-3'}>
        {/*row-cols-* - set the cards width by setting amount of cards in row*/}
        {cardsArray}
      </Row>
    </Container>
  )
}

export default Cards

这是 CardsContainer 中的代码:

const mapStateToProps = (state) => {
  return {
    cardsData: state.homePage.cardsData
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    addCardData: (data) => {
      dispatch(addCardsData(data))
    }
  }
}

const CardsContainer = connect(mapStateToProps, mapDispatchToProps)(Cards);

export default CardsContainer

这是减速器中的代码:

...
homePageCardsData = 'HOMEPAGE-CARDS-DATA'

initialState = {...} - includes "cardsData: {}"

const homePageReducer = (state = initialState, action) => {
  let stateCopy;
  switch (action.type) {
    case homePageCardsData: {
      stateCopy = {...state, cardsData: action.data}
      break
    }
    ...
    default: return state;
  }
  return stateCopy;

  ...... - some functions here (not necessary to know)
}

export const addCardsData = (data) => ({
  type: homePageCardsData,
  data: data
})

当我尝试类似的事情时:

const addCard = props.addCardData

axios.get('https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e')
  .then(response => {
    addCard(response.data)
  })

我在本地主机上出现延迟(在主页上!!),所有内容都开始缓慢渲染,并且 70% 的情况下,卡片块未渲染。在其他情况下,它可以在一段时间后渲染(很少机会)。在 AdminPanel 页面上,我渲染 Cards 因为我在测试菜单时需要查看更改,我收到“TypeError:addCard 不是函数。”

如果我从组件中删除此代码 - 一切都会正常。

我还必须说我使用了“调试器”并将其放在 homePageCardsData 中。脚本在调试器上停止(在 StateCopy 之后和 break 之前)。这意味着脚本是正确的,dispatch 可以工作,我可以进入案例 homePageCardsData

P粉475315142
P粉475315142

全部回复(1)
P粉807471604

问题出在 Cards 组件中,它直接在组件的函数体中将 Axios GET 请求作为无意的副作用。这很可能会创建一个渲染循环,或者至少在每次 Cards 渲染时发出 GET 请求。

将此代码移至 useEffect 挂钩中,以便在组件安装后调用它。

示例:

const Cards = ({ addCardsData, cardsData }) => {
  useEffect(() => {
    axios
      .get("https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e")
      .then((response) => {
        addCardsData(response.data);
      });
  }, [addCardsData]);

  let cardsArray = Object.keys(cardsData).map((card) => (
    <OfferCard
      key={card.id}
      bg={cardsData[card].bg}
      id={cardsData[card].tagId}
      title={cardsData[card].title}
      text={cardsData[card].text}
      button={
        <Container fluid>
          <Row className={"row-cols-auto"}>
            {cardsData[card].button.map((button) => (
              <CardsButton
                key={button.id}
                link={button.link}
                type={button.type}
                class={button.class}
                name={button.name}
              />
            ))}
          </Row>
        </Container>
      }
    />
  ));

  return (
    ...
  );
};

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

const mapDispatchToProps = {
  addCardsData
};

const CardsContainer = connect(mapStateToProps, mapDispatchToProps)(Cards);

您使用的是相当旧的 Redux 代码,我们通常不再使用 connect 高阶组件,因为 useDispatchuseSelector 挂钩取代了它的用法。目前的标准是使用 Redux-Toolkit确实减少了您需要编写的样板文件的数量。

以下是更新建议示例:

import { useDispatch, useSelector } from "react-redux";
...

const Cards = () => {
  const dispatch = useDispatch();
  const cardsData = useSelector(state => state.homePage.cardsData);

  useEffect(() => {
    axios
      .get("https://mocki.io/v1/8cb0f160-92f7-4cf8-a6c1-f63690df514e")
      .then((response) => {
        dispatch(addCardsData(response.data));
      });
  }, [dispatch]);

  let cardsArray = Object.keys(cardsData).map((card) => (
    <OfferCard
      key={card.id}
      bg={cardsData[card].bg}
      id={cardsData[card].tagId}
      title={cardsData[card].title}
      text={cardsData[card].text}
      button={
        <Container fluid>
          <Row className={"row-cols-auto"}>
            {cardsData[card].button.map((button) => (
              <CardsButton
                key={button.id}
                link={button.link}
                type={button.type}
                class={button.class}
                name={button.name}
              />
            ))}
          </Row>
        </Container>
      }
    />
  ));

  return (
    ...
  );
};

reducer 代码、操作类型、操作创建者...全部由单个状态切片替换。

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  cardsData: {},
  ... other home page state ...
};

const homePageSlice = createSlice({
  name: "homePage",
  initialState,
  reducers: {
    addCardsData: (state, action) => {
      state.cardsData = action.payload;
    },
    ... other reducer cases ...
  }
});

export const {
  addCardsData,
  ... other generated actions ...
} = homePageSlice.actions;

export default homePageSlice.reducer;

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号