【问题标题】:React conditional rendering causes multiple api callsReact 条件渲染导致多次 api 调用
【发布时间】:2018-12-05 05:35:04
【问题描述】:

我正在使用 React + Redux + Redux-Saga。

在我的场景中,我调用 2 个 api - 用于配置和数据(在获取配置后)

我在调用 Data 时遇到问题。简而言之:

这是有效的:

TestRoute.jsx 文件(尚未使用isConfig):

import React from 'react';
import { connect } from 'react-redux';
import TestComponent from '../components/Test';

const Test = ({ isConfig }) => <div>
  <TestComponent />
  <TestComponent />
  <TestComponent />
  <TestComponent />
</div>

const mapStateToProps = state => ({
  isConfig: !!state.config.payload.tenantId
});

export default connect(mapStateToProps)(Test);

TestComponent.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { dataRequestInit } from '../state/actions/data';

class Test extends Component {
  componentDidMount() {
    this.props.dataRequestInit('https://data/api/url');
  }

  render() {
    return <p>hello</p>;
  }
}

const mapStateToProps = state => ({})

export default connect(
  mapStateToProps,
  { dataRequestInit }
)(Test);

传奇文件:

const getIsFetching = (state, url) => state.data.isFetching.includes(url);

function* fetchData(url) {
  try {
    const isFetching = yield select(getIsFetching, url);

    if (!isFetching) {
      yield put(actions.fetchDataIsFetching(url));

      const response = yield call(api, url);

      console.log('response', response);
    }
  } catch (err) {
    console.log('handle error', err);
  }
}

export default function* DataSaga() {
  yield takeEvery(actionTypes.FETCH_DATA_INIT, fetchData);
}

在这种情况下一切正常 - 第一次调用设置 isFetching 并且正在执行一个 api 请求。 Redux DevTools view

但如果我重新创建我的 Route 文件以开始使用 isConfig 标志并有条件地呈现 TestComponents:

const Test = ({ isConfig }) =>
  isConfig && (
    <div>
      <TestComponent />
      <TestComponent />
      <TestComponent />
      <TestComponent />
    </div>
  );

一切都变得疯狂,4 个 api 调用将发送到服务器。这是因为首先启动了 4x DATA/FETCH_INIT 和随后的 4x DATA/SET_IS_FETCHING 操作 Redux DevTools view 而不是预期的:1x DATA/FETCH_INIT 1x DATA/SET_IS_FETCHING 3x DATA/FETCH_INIT 像以前一样。

有人可以向我解释为什么会这样吗?我在这里缺少什么以及如何解决这个问题?

【问题讨论】:

    标签: reactjs react-redux redux-saga


    【解决方案1】:

    我可以看到您的问题,您正在安装相同的组件 4 次,见下文:

    componentDidMount() {
      this.props.dataRequestInit('https://data/api/url');
    }
    

    然后你渲染 4 次:

      <TestComponent />
      <TestComponent />
      <TestComponent />
      <TestComponent />
    

    这将为每个组件触发一个单独的函数调用实例,为“isFetching”设置一个变量不会阻止其他组件进行 API 调用。

    还有一点需要注意,如果这个组件需要渲染 4 次,而且它们都需要相同的数据,最好将控制权交给父组件,获取一次数据,然后传递给每个实例中的组件,如下所示:

    <TestComponent data={state.data}/>
    

    此外,此操作的减速器案例应如下所示:

    switch (action.type) {
      case AUTH_REQUEST:
        return {
          ...state
        }
    

    带有扩展运算符的状态变量,它保留先前操作的状态,在您的情况下是获取变量。

    希望对你有帮助

    劳埃德

    【讨论】:

    • 嗨。感谢您的回答,但在我的情况下 isFetching 在 Redux Store 中(我首先应该强调这一点,抱歉),所以它对所有组件都是通用的。不是吗?
    • 不,它不会那样工作,数据获取初始化动作将被触发 4 次,因为每次运行调度时都会触发它,此时它也不关心状态,也请分享您的 reducer 代码,如果您没有正确设置 reducer,您的 fetch init 操作实际上会在每次调用时清除它,因此您最终也会调用 4 个 API。
    猜你喜欢
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2022-06-12
    • 2020-05-09
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多