簡體   English   中英

React 組件正在無限地重新渲染

[英]React component is re-rendering infinitely

首先,我真的很陌生; 所以,抱歉,對於初學者的問題。

我有一個帶有 Redux 和 Redux Saga 的 React 應用程序。

其中一個組件如下所示:

import { TableContainer, TableHead, TableRow } from '@material-ui/core';
import Paper from '@material-ui/core/Paper';
import makeStyles from '@material-ui/core/styles/makeStyles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ProgramCategory } from '../model/program-category';
import { ProgramCategoryItemRow } from '../ProgramGategoryItemRow/ProgramCategoryItemRow';
import { ProgramCategoryActions } from '../store/program-category.actions';
import { ProgramCategorySelectors } from '../store/program-category.selectors';

const useStyles = makeStyles({
  table: {
    width: '100%',
  },
  tableHeadCell: {
    fontWeight: 'bold',
  },
});

export interface ProgramCategoriesTableProps {
  isLoaded: boolean;
  categories: ProgramCategory[];
  fetchAllCategories: () => void;
}

export const PureProgramCategoriesTable: React.FC<ProgramCategoriesTableProps> = ({
  isLoaded,
  categories,
  fetchAllCategories,
}) => {
  useEffect(() => {
    console.error('in useEffect');
    fetchAllCategories();
  });

  const styles = useStyles();

  return (
    <TableContainer component={Paper}>
      // the rest
      <TableBody>
          {categories.map(c => (
            <ProgramCategoryItemRow category={c} />
          ))}
      </TableBody>
    </TableContainer>
  );
};

const mapStateToProps = createSelector(
  [ProgramCategorySelectors.isLoaded, ProgramCategorySelectors.getAll],
  (isLoaded, categories) => ({ isLoaded, categories }),
);

const mapDispatchToProps = {
  fetchAllCategories: ProgramCategoryActions.fetchAll.start,
};

export const ProgramCategoriesTable = connect(mapStateToProps, mapDispatchToProps)(PureProgramCategoriesTable);

處理ProgramCategoryActions.fetchAll.start如下:

import { call, put, takeLatest } from 'redux-saga/effects';
import { ProgramCategoryApi } from '../services/program-category.api';
import { ProgramCategoryActions } from './program-category.actions';

function* handleFetchAll() {
  try {
    const categories = yield call(ProgramCategoryApi.fetchAll);
    yield put(ProgramCategoryActions.fetchAll.success(categories));
  } catch (e) {
    yield put(ProgramCategoryActions.fetchAll.failure(e));
  }
}

export function* programCategorySagas() {
  yield takeLatest(ProgramCategoryActions.fetchAll.start.type, handleFetchAll);
}

一切都說得通,但是發生的事情我的動作代碼會一遍又一遍地執行。 再深入研究一下,似乎效果鈎子也被一遍又一遍地執行。 如果我理解正確,發生這種情況是因為狀態中的數據正在發生變化,組件再次重​​新渲染。 但是,它導致無限循環。 我究竟做錯了什么? 設置這種組件的正確方法是什么?

我發現的選項之一是將傳奇更改為:

function* handleFetchAll() {
  try {
    const alreadyLoaded = select(ProgramCategorySelectors.isLoaded);
    if (!alreadyLoaded) {
      const categories = yield call(ProgramCategoryApi.fetchAll);
      yield put(ProgramCategoryActions.fetchAll.success(categories));
    }
  } catch (e) {
    yield put(ProgramCategoryActions.fetchAll.failure(e));
  }
}

所以,它只調用 api 一次; 它似乎以這種方式工作得很好。 但是,這是正確的解決方案嗎?

正如評論中所建議的,我嘗試為效果添加依賴項:

useEffect(() => {
    fetchAllCategories();
  }, []);

現在,我收到一個錯誤:

./src/program/ProgramCategoriesTable/ProgramCategoriesTable.tsx 第 37:6 行:React Hook useEffect 缺少依賴項:'fetchAllCategories'。 包括它或刪除依賴項數組。 如果 'fetchAllCategories' 更改過於頻繁,請找到定義它的父組件並將該定義包裝在 useCallback react-hooks/exhaustive-deps 中

問題在這里,

useEffect(() => {
  console.error('in useEffect');
  fetchAllCategories();
});

來自 react 文檔:useEffect 是否在每次渲染后運行? 是的! 默認情況下,它會在第一次渲染之后和每次更新之后運行。 (我們稍后將討論如何自定義它。)與其考慮“安裝”和“更新”,您可能會發現更容易認為效果發生在“渲染之后”。 React 保證 DOM 在它運行效果時已經更新。

https://reactjs.org/docs/hooks-effect.html

你必須在最后傳遞和依賴數組。

useEffect(() => {
  console.error('in useEffect');
  fetchAllCategories();
}, []);

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM