Во-первых, я действительно новичок, чтобы реагировать; Итак, извините, для начинающих вопросов.
У меня есть приложение React с Redux и Redux Saga.
Один из компонентов выглядит так:
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);
}
Все имеет смысл, но что происходит, мой код действия выполняется снова и снова. Углубившись в это немного больше, кажется, что ловушка эффекта также выполняется снова и снова. Если я правильно понимаю, это происходит из-за того, что данные в состоянии меняются, компонент снова перерисовывается. Но это приводит к бесконечному l oop. Что я делаю неправильно? Как правильно настроить этот тип компонента?
Один из найденных вариантов - изменить сагу на:
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 response-hooks / исчерпывающее-deps