Repository: microsoft/playwright
File: packages/html-reporter/src/reportView.tsx (TypeScript)

Code before:
          }
          break;
        case 'ArrowRight':
          if (next) {
            event.preventDefault();
            navigate(testResultHref({ test: next }) + filterParam);
          }
          break;
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [prev, next, filterParam, q, searchParams]);

  React.useEffect(() => {
    if (reportTitle)
      document.title = reportTitle;
    else
      document.title = 'Playwright Test Report';
  }, [reportTitle]);

  return <div className='htmlreport vbox px-4 pb-4'>
    <main>
      {report && <GlobalFilterView stats={report.json().stats} filterText={filterText} setFilterText={setFilterText} />}
      <Route predicate={React.useCallback(params => !params.has('testId') && !params.has('speedboard'), [])}>
        <TestFilesHeader report={report?.json()} filteredStats={filteredStats} metadataVisible={metadataVisible} toggleMetadataVisible={() => setMetadataVisible(visible => !visible)}/>
        <TestFilesView
          files={testModel.files}
          expandedFiles={expandedFiles}
          setExpandedFiles={setExpandedFiles}
          projectNames={report?.json().projectNames || []}
        />
      </Route>
      <Route predicate={React.useCallback(params => params.has('speedboard') && !params.has('testId'), [])}>
        <TestFilesHeader report={report?.json()} filteredStats={filteredStats} metadataVisible={metadataVisible} toggleMetadataVisible={() => setMetadataVisible(visible => !visible)}/>
        {report && <Speedboard report={report} tests={testModel.tests} />}
      </Route>
      <Route predicate={React.useCallback(params => params.has('testId'), [])}>
        {report && <TestCaseViewLoader report={report} next={next} prev={prev} testId={testId} testIdToFileIdMap={testIdToFileIdMap} />}
      </Route>
    </main>
  </div>;
};

const TestCaseViewLoader: React.FC<{
  report: LoadedReport,
  testId: string | null,
  next?: TestCaseSummary,
  prev?: TestCaseSummary,
  testIdToFileIdMap: Map<string, string>,

Review comment (suggestion):
Please don't call React hooks like this. While it works, it's not expected/idiomatic and makes it very easy to conditionally call them.

Thank you for using `useCallback` for these though.

Code after:
          navigate(filterWithQuery(searchParams, 's:failed', false));
          break;
        case 'ArrowLeft':
          if (prev) {
            event.preventDefault();
            searchParams.delete('testId');
            navigate(testResultHref({ test: prev }, searchParams) + filterParam);
          }
          break;
        case 'ArrowRight':
          if (next) {
            event.preventDefault();
            searchParams.delete('testId');
            navigate(testResultHref({ test: next }, searchParams) + filterParam);
          }
          break;
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [prev, next, filterParam, q, searchParams]);

  React.useEffect(() => {
    if (reportTitle)
      document.title = reportTitle;
    else
      document.title = 'Playwright Test Report';
  }, [reportTitle]);

  return <div className='htmlreport vbox px-4 pb-4'>
    <main>
      {report && <GlobalFilterView stats={report.json().stats} filterText={filterText} setFilterText={setFilterText} />}
      <Route predicate={testFilesRoutePredicate}>
        <TestFilesHeader report={report?.json()} filteredStats={filteredStats} metadataVisible={metadataVisible} toggleMetadataVisible={() => setMetadataVisible(visible => !visible)}/>
        <TestFilesView
          files={testModel.files}
          expandedFiles={expandedFiles}
          setExpandedFiles={setExpandedFiles}
          projectNames={report?.json().projectNames || []}
        />
      </Route>
      <Route predicate={speedboardRoutePredicate}>
        <TestFilesHeader report={report?.json()} filteredStats={filteredStats} metadataVisible={metadataVisible} toggleMetadataVisible={() => setMetadataVisible(visible => !visible)}/>
        {report && <Speedboard report={report} tests={testModel.tests} />}
      </Route>
      <Route predicate={testCaseRoutePredicate}>
        {report && <TestCaseViewLoader report={report} next={next} prev={prev} testId={testId} testIdToFileIdMap={testIdToFileIdMap} />}
      </Route>
    </main>
  </div>;