Repository: neherlab/covid19_scenarios
File: src/components/Main/Main.tsx (TypeScript)

Code before:
    population: scenarioState.data.population,
    epidemiological: scenarioState.data.epidemiological,
    simulation: scenarioState.data.simulation,
    containment: scenarioState.data.containment,
  }

  const [debouncedRun] = useDebouncedCallback(
    (params: AllParams, scenarioState: State, severity: SeverityTableRow[]) =>
      runSimulation(params, scenarioState, severity, setResult, setEmpiricalCases),
    500,
  )

  useEffect(() => {
    // runs only once, when the component is mounted
    const autorun = LocalStorage.get<boolean>(LOCAL_STORAGE_KEYS.AUTORUN_SIMULATION)
    setAutorunSimulation(autorun ?? false)

    // if the link contains query, we're executing the scenario (and displaying graphs)
    // this is because the page was either shared via link, or opened in new tab
    if (window.location.search) {
      debouncedRun(allParams, scenarioState, severity)

      // At this point the scenario params have been captured, and we can clean up the URL.
      updateBrowserURL('/')
    }
  }, [autorunSimulation, debouncedRun, scenarioState, severity]) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (autorunSimulation) {
      debouncedRun(allParams, scenarioState, severity)
    }
  }, [autorunSimulation, debouncedRun, scenarioState, severity]) // eslint-disable-line react-hooks/exhaustive-deps

  const [validateFormAndUpdateState] = useDebouncedCallback((newParams: AllParams) => {
    return schema
      .validate(newParams)
      .then((validParams) => {
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.population, validParams.population)) {
          scenarioDispatch(setPopulationData({ data: validParams.population }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.epidemiological, validParams.epidemiological)) {
          scenarioDispatch(setEpidemiologicalData({ data: validParams.epidemiological }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.simulation, validParams.simulation)) {
          scenarioDispatch(setSimulationData({ data: validParams.simulation }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.containment, validParams.containment)) {

Review comment (suggestion):
The current version `[]` gives run once (componentDidMount) semantics which is what I think we want to limit the LocalStorage and URL futzing. 

Code after:
    population: scenarioState.data.population,
    epidemiological: scenarioState.data.epidemiological,
    simulation: scenarioState.data.simulation,
    containment: scenarioState.data.containment,
  }

  const [debouncedRun] = useDebouncedCallback(
    (params: AllParams, scenarioState: State, severity: SeverityTableRow[]) =>
      runSimulation(params, scenarioState, severity, setResult, setEmpiricalCases),
    500,
  )

  useEffect(() => {
    // runs only once, when the component is mounted
    const autorun = LocalStorage.get<boolean>(LOCAL_STORAGE_KEYS.AUTORUN_SIMULATION)
    setAutorunSimulation(autorun ?? false)

    // if the link contains query, we're executing the scenario (and displaying graphs)
    // this is because the page was either shared via link, or opened in new tab
    if (window.location.search) {
      debouncedRun(allParams, scenarioState, severity)

      // At this point the scenario params have been captured, and we can clean up the URL.
      updateBrowserURL('/')
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (autorunSimulation) {
      debouncedRun(allParams, scenarioState, severity)
    }
  }, [autorunSimulation, debouncedRun, scenarioState, severity]) // eslint-disable-line react-hooks/exhaustive-deps

  const [validateFormAndUpdateState] = useDebouncedCallback((newParams: AllParams) => {
    return schema
      .validate(newParams)
      .then((validParams) => {
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.population, validParams.population)) {
          scenarioDispatch(setPopulationData({ data: validParams.population }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.epidemiological, validParams.epidemiological)) {
          scenarioDispatch(setEpidemiologicalData({ data: validParams.epidemiological }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.simulation, validParams.simulation)) {
          scenarioDispatch(setSimulationData({ data: validParams.simulation }))
        }
        // NOTE: deep object comparison!
        if (!_.isEqual(allParams.containment, validParams.containment)) {