React useParams 返回 'string |未定义'

问题描述 投票:0回答:2

我在其他地方看到过这个问题,但没有一个答案对我有帮助。我在 url 中使用了一个参数,我想使用 useParam 挂钩访问它,然后查询我的后端。

解构后的参数类型为 'string | undefined' - 有没有办法明确键入解构的查询参数?我想避免有未定义的值。我知道我可以处理期望参数的函数中的未定义值,但如果可能的话,我宁愿从源头上删除问题。

其他答案建议将解构的参数值与路由组件中规定的参数名称进行匹配,但我的已经匹配了。这可能与“/journalEntries”下的嵌套路由有关,即因为其他路由 - 没有参数 - 可能在“journalEntries”路由上?我试图通过删除其他子路线来解决这个问题,但没有帮助。

路由:

const Routing = () => {
  return (
    <MainViewContainer>
      <NavBar />
      <>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/thoughtRecords" element={<ThoughtRecordPage />} />

          <Route path="/journalEntries">
            <Route
              index
              element={
                <JournalPage>
                  <JournalContainer />
                </JournalPage>
              }
            />

=========================================================
     ROUTE I WANT TO DESTRUCTURE THE 'id' PARAMETER FROM:

            <Route
              path=":id"
              element={
                <JournalPage>
                  <JournalEntry />
                </JournalPage>
              }
            />
=========================================================

            <Route
              path="create"
              element={
                <JournalPage>
                  <JournalEntryForm />
                </JournalPage>
              }
            />
          </Route>
        </Routes>
      </>
    </MainViewContainer>
  );
};
export default Routing;

包含指向单个“日记条目”的链接的组件:

const JournalContainer = () => {
  const { journalEntries } = useDataContext();

  return (
    <>
      <div className="flex flex-col items-center">
        {journalEntries.map((journalEntry) => {
          return (
            <div
              className="w-1/3 border flex justify-between p-1 m-1"
              key={journalEntry._id}
            >


======================================================================
              LINK TO JOURNAL ENTRY

              <Link
                to={`/journalEntries/${journalEntry._id}`}
                className="w-3/4 flex justify-between"
              >
======================================================================


                <span className="">{journalEntry.title}</span>
                <span className="text-xs">
                  {new Date(journalEntry.createdAt).toDateString()}
                </span>
              </Link>
              <button
                onClick={async () => await deleteJournalEntry(journalEntry._id)}
                className="mr-0"
              >
                Delete
              </button>
            </div>
          );
        })}
        <Link
          className="w-1/3 border text-center p-1 m-1"
          to={'/journalEntries/create'}
        >
          Create a Journal Entry
        </Link>
      </div>
    </>
  );
};

export default JournalContainer;

依赖于解构参数的'Journal Entry'组件:

  const { id } = useParams(); // is typed as 'string | undefined'

  const methods = useForm({
    defaultValues: async () => await getJournalEntryById(id), // this function expects a string
  });
  const navigate = useNavigate();

  const [saveCopy, setSaveCopy] = useState(false);
  const [readOnly, setReadOnly] = useState(true);

  const submissionHandler: SubmitHandler<CreateJournalEntryType> = async (
    data
  ) => {
    await updateJournalEntryById(id, data); // this function expects a string
    if (saveCopy) {
      writeJournalEntryToFile(data);
    }
    navigate('/journalEntries');
  };

  return (
    <FormProvider {...methods}>
      <form
        className="flex flex-col justify-evenly items-center border p-10 h-1/2"
        onSubmit={methods.handleSubmit(submissionHandler)}
      >
        <button className="mr-auto" onClick={() => navigate(-1)}>
          Go Back
        </button>
        <JournalEntryFormFields readOnly={readOnly} setReadOnly={setReadOnly} />
        <div className="flex w-full justify-evenly items-center">
          <button type="submit" className="border p-2 m-1">
            Submit Journal Entry
          </button>
          <div className="flex items-center border p-1">
            <input
              type="checkbox"
              className="m-1"
              onChange={() => setSaveCopy(!saveCopy)}
            />
            <label className="m-1" htmlFor="save-journal-entry-checkbox">
              Save a copy to file
            </label>
          </div>
        </div>
      </form>
    </FormProvider>
  );
};

export default JournalEntry;
  • 确保参数名称匹配
  • 尝试渲染单一路线
typescript url react-hooks parameters react-router
2个回答
0
投票

在 React Router 中,TypeScript 编译器目前无法推断参数值不是未定义的。

相反,你可以做的是使用不变检查。这种方法广受欢迎,并在 React Router 内部使用,以断言程序状态的给定属性始终为真。

不变检查的工作原理如下:

const {id} = useParams();
invariant(id); // From this point on "id" is correctly treated as non-undefined

“不变量”的实现可能如下所示:

function invariant(value: unknown): asserts value {
  if (value) {
    return;
  }
  
  throw new Error("Invariant violation");
}

或者,您可以从 https://npmjs.com 下载不变量的众多实现之一 请注意:Facebook 不变量的镜像包含专为 Facebook 目的设计的错误处理逻辑。


0
投票

如果您知道

id
路由路径参数将始终是定义的字符串,那么您可以简单地键入/转换参数值。像下面这样简单的东西应该/可以工作。

const { id } = useParams() as { id: string };
© www.soinside.com 2019 - 2024. All rights reserved.