const LeveragePage: NextPage = () => {

  const [leverages, setLeverages] = useState<Array<Leverage>>([]);
  const [filteredLeverages, setFilteredLeverages] = useState<Array<Leverage>>([]);

  const [searchInputValue, setSearchInputValue] = useState("");
  const [localChangedLeverage, setLocalChangedLeverage] = useState<{symbol: string, value: number|undefined}>({
    symbol: "symbol",
    value: undefined,
  });
  const onChangeLeverage = (symbol: string, value: number|undefined) => {
    setLocalChangedLeverage({symbol, value});
  };

  useEffect(() => {
    if (undefined !== localChangedLeverage.value) {
      setChangedLeverages({
        ...changedLeverages,
        [localChangedLeverage.symbol]: localChangedLeverage.value,
      });
    } else {
      setChangedLeverages(Object.keys(changedLeverages).reduce(
        (acc, key) => {
          return key === localChangedLeverage.symbol
            ? acc
            : {...acc, [key]: changedLeverages[key]};
        },
        {},
      ));
    }
  }, [localChangedLeverage]);
     return             {
                    filteredLeverages.map((leverage, index) => {
                      return <Grid item sm={12} md={4} key={leverage.symbol}>
                        <LeverageForm
                          index={index}
                          leverage={leverage}
                          selected={undefined !== changedLeverages[leverage.symbol]}
                          onChange={onChangeLeverage}
                          value={changedLeverages[leverage.symbol]}
                        />
                      </Grid>;
                    })
                  }

};

export default LeveragePage;
const LeverageForm = memo(
  function LeverageForm(
    {leverage, index, value, selected, onChange}: LeverageFormProps
  ) {
    const [leverageValue, setLeverageValue] = useState<number>(value || leverage.leverage);
    const [checked, setChecked] = useState(selected);

    useEffect(() => {
      onChange(leverage.symbol, checked ? leverageValue : undefined);
    }, [leverageValue, checked]);

    useEffect(() => {
      if (!checked && leverage.leverage !== leverageValue) {
        setChecked(true);
      }
    }, [leverageValue]);

    useEffect(() => {
      if (checked !== selected) {
        setChecked(selected);

        if (!selected) {
          setLeverageValue(leverage.leverage);
        }
      }
    }, [selected]);

import { createSlice } from "@reduxjs/toolkit";
import {HYDRATE} from "next-redux-wrapper";
import { Leverage } from "../actions/cicap-diary-trades";

interface LeverageSlice {
  leverage: { [key: string]: Leverage },
}

const initialState: LeverageSlice = {
  leverage: {},
};

export const leverageSlice = createSlice({
  name: "leverageSlice",
  initialState,
  reducers: {
    setLeverage(state, action) {
      state.leverage = action.payload;
    },
  },
  extraReducers: {
    [HYDRATE]: (state, action) => {
      return {
        ...state,
        ...action.payload,
      };
    },
  },
});

export const {
  setLeverage,
} = leverageSlice.actions;

export default leverageSlice.reducer;
1. В редаксе у leverages должен быть тип например {[key: string]: Leverage}, где в key хранится symbol.
Тогда в LeverageForm можно передать только symbol и index. Доставать данные уже внутри LeverageForm по symbol:
const leverages = useSelector((state: AppState) => state.leverageSlice.leverages[symbol]);
Тогда LeverageForm будет ререндериться только при изменении плеча по его монете.
2. changed можно сделать свойством объекта Leverage.

3. LeverageForm у нас отрисовывает 223 раза, потому что  в LeveragePage 223 symbols. Нужно сделать так, чтобы когда менялся один из объектов по leverage state.leverage[symbol], он изменлся, а остальные 22 символа не изменялись и LeverageForm не перерисовывался, а перерисовывался только там где я меняю данные.
То есть должна быть оптимизация