I have a parent component that has an array in state. It maps over the array and passes items to child components.
import React, { useState, useEffect } from "react";
import { Channel } from "../../../constants";
import { CommandLineArguments } from "../../../main/ipcHandlers";
import { Conversion, Converter } from "../Converter/Converter";
export function App() {
  const [commandLineArguments, setCommandLineArguments] = useState<null | CommandLineArguments>(null);
  const [conversions, setConversions] = useState<Conversion[]>([]);
  function setConversion(filepath: string, partial: Partial<Conversion>) {
    const updated = conversions
      .filter((conversion) => conversion.filepath === filepath)
      .map((conversion) => ({ ...conversion, ...partial }));
    const rest = conversions.filter((conversion) => conversion.filepath !== filepath);
    setConversions([...rest, ...updated]);
  }
  useEffect(function getCommandLineArgumentsEffect() {
    async function asyncReadSvgFile() {
      const args = await window.bridgeToMainProcessApi.invoke(Channel.GetCommandLineArguments);
      const s = (args.input || []).map((path) => {
        return { filepath: path };
      });
      setConversions(s);
    }
    asyncReadSvgFile();
  }, []);
  return (
    <div>
      {conversions.map((c) => (
        <Converter
          proxy=""
          setConversion={setConversion}
          key={c.filepath}
          filepath={c.filepath}
          svg={c.svg}
          processedSvg={c.processedSvg}
          tgml={c.tgml}
        />
      ))}
    </div>
  );
}
The children invoke the callback to update the conversions.
import React, { useEffect } from "react";
import compose from "lodash/fp/compose";
import { XmlView, XmlType, ViewType } from "../XmlView";
import { Channel, defaultProxy } from "../../../constants";
import { prepareSvg, convertSvg } from "../../../process";
import { filenameWithoutExtension, filenameFromPath } from "../App/files";
export type Conversion = {
  filepath: string;
  svg?: string;
  processedSvg?: string;
  tgml?: string;
};
type Props = Conversion & {
  proxy: string;
  setConversion(filepath: string, conversion: Partial<Conversion>): void;
};
export function Converter(props: Props) {
  const { filepath, svg, processedSvg, tgml, proxy, setConversion } = props;
  useEffect(
    function readSvgFileEffect() {
      console.log("read1");
      async function asyncReadSvgFile() {
        console.log("read2");
        const files = await window.bridgeToMainProcessApi.invoke(Channel.ReadFiles, [filepath]);
        const svg = files[0].content;
        setConversion(filepath, { svg });
      }
      asyncReadSvgFile();
    },
    [filepath]
  );
  useEffect(
    function prepareSvgEffect() {
      async function asyncprepareSvg() {
        if (!svg) {
          return;
        }
        const processedSvg = await prepareSvg(svg, defaultProxy ? defaultProxy : proxy);
        setConversion(filepath, { processedSvg });
      }
      asyncprepareSvg();
    },
    [svg]
  );
  useEffect(
    function convertSvgEffect() {
      async function asyncConvertSvg() {
        if (!processedSvg) {
          return;
        }
        const tgml = await convertSvg(processedSvg, compose(filenameWithoutExtension, filenameFromPath)(filepath));
        setConversion(filepath, { tgml });
      }
      asyncConvertSvg();
    },
    [processedSvg]
  );
  return (
    <div>
      {svg && <XmlView serialized={svg} xmlType={XmlType.Svg} viewType={ViewType.Image} />}
      {processedSvg && <XmlView serialized={processedSvg} xmlType={XmlType.ProcessedSvg} viewType={ViewType.Image} />}
      {tgml && <XmlView serialized={tgml} xmlType={XmlType.Tgml} viewType={ViewType.Image} />}
      {svg && <XmlView serialized={svg} xmlType={XmlType.Svg} viewType={ViewType.Code} />}
      {processedSvg && <XmlView serialized={processedSvg} xmlType={XmlType.ProcessedSvg} viewType={ViewType.Code} />}
      {tgml && <XmlView serialized={tgml} xmlType={XmlType.Tgml} viewType={ViewType.Code} />}
    </div>
  );
}
I don't understand why this causes an infinite rendering loop. I understand that calling setConversions causes the parent to re-render and pass new props to the children. I guess that might cause all the children to be recreated from scratch. Feel free to provide a better explanation of what is happening.
Regardless, my main question is: how do I get around the infinite re-rendering?
 
     
    