Using the getContractsFromAPI action, I get a list of contracts that are in the API, then using useState and renderContracts, I display them on the page, but this starts an endless call to useEffect
const [contracts, setContracts] = useState({});
const contractsList = useAppSelector(({ contractsList }) => contractsList);
useEffect(() => {
dispatch(getContractsFromAPI());
setContracts(contractsList);
}, [contractsList, dispatch]);
return (
<div>
<h2>Contracts:</h2>
<ul className={styles.contractsList}>{renderContracts(contracts)}</ul>
</div>
);
How can the problem be solved? I tried to remove [contractsList, dispatch] from useEffect, but then the initial render does not occur when the page is opened
CodePudding user response:
Put dispatch(getContractsFromAPI()); in it's own useEffect
useEffect(() => {
setContracts(contractsList);
}, [contractsList, setContracts]);
useEffect(() => {
dispatch(getContractsFromAPI());
}, [dispatch, getContractsFromAPI]);
you were getting an infinite loop because getContractsFromAPI apparently edit contractsList. The easy solution is having getContractsFromAPI in a useEffect that does not watch for change on contractsList
CodePudding user response:
If you don't really need a shallow copy of the contracts in your component's local state, get rid of the local state and just use them from the selector.
function ContractsComponent() {
const contracts = useAppSelector(({ contractsList }) => contractsList);
// Get contracts from API on mount
useEffect(() => {
dispatch(getContractsFromAPI());
}, [dispatch]);
if (!contracts) return <>Loading...</>;
return (
<div>
<h2>Contracts:</h2>
<ul className={styles.contractsList}>{renderContracts(contracts)}</ul>
</div>
);
}