简体   繁体   中英

Solve the react-hooks/exhaustive-deps when updating redux in useEffect

Can you help me solve useEffect riddles?

I want to satisfy the linter react-hooks/exhaustive-deps rule but also have a component which does not re-render all the time. My component should aggregate data if it is loading for the first time. This data is fetched from redux, then the summation is done and the data is stored back to redux.

As explained in this question , I could move the aggregation to the component where the data is added, but this would force me to update the arrays more often, once either stocks or transaction is added and this even I never view the aggregate.

This question also points to a post by Dan Abramov not to disable the linter rule. Which let me came to the conclusion just leaving something out in the useEffect array is not the way to go — as it is the case in my example.

Now the question is how to solve this?

import React, { useEffect } from "react";
import { useDispatch } from "react-redux";

import { ITransactionArray } from "../../../store/account/types";
import { IStockArray, STOCKS_PUT } from "../../../store/portfolio/types";
import { useTypedSelector } from "../../../store/rootReducer";
import { AppDispatch } from "../../../store/store";

const aggregateStockQuantities = (
    stocks: IStockArray,
    transactions: ITransactionArray
): IStockArray => {
    console.log("run Value/aggregateStockQuantities");

    const newStocks = [...stocks];
    newStocks.forEach((s) => {
        s.quantity = 0;
        return s;
    });

    transactions.forEach((t) => {
        newStocks.forEach((s) => {
            if (s.quantity !== undefined && t.isin === s.isin) {
                s.quantity += t.quantity;
            }

            return s;
        });
    });

    return newStocks;
};

const Test: React.FC = () => {
    const dispatch: AppDispatch = useDispatch();
    const { stocks } = useTypedSelector((state) => state.portfolio);
    const { transactions } = useTypedSelector((state) => state.account);
    const stockQuantities = aggregateStockQuantities(stocks, transactions);

    useEffect(() => {
        dispatch({
            type: STOCKS_PUT,
            payload: stockQuantities,
        });
    }, [dispatch]);
    // only works if I leave out stockQuantities
    // but then warning:  React Hook useEffect has a missing dependency: 'stockQuantities'. Either include it or remove the dependency array  react-hooks/exhaustive-deps


    // Render
}

Update #1: Had to change the aggregateStockQuantities so quantity is null at the start.

I would advice making a selector that only selects aggregateStockQuantities from the redux state.

And move the const stockQuantities = aggregateStockQuantities(stocks, transactions); inside the useEffect hook.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM