URL 搜索参数被替换 - Remix 运行

URL search parameters gets replaced - Remix Run

我正在搜索 UI,其中有很多过滤器,当有人 selects/checks 选项时,我希望将其作为 URL 参数。我已经使用 Remix.run 文档中建议的技术在过滤器中提出多种形式。每次提交一组过滤器时,选定的旧参数都会消失。这是我的代码,

<Panel header="Status" key="status">
      <Form
        name="search"
        action='/search'
        method="get"
        onChange={(e) => submit(e.currentTarget, { replace: false })}
      >
        <ul>
          <li>
            <Checkbox
              name="status"
              value="buy_now"
              defaultChecked={status.includes('buy_now')}
            >
              Buy Now
            </Checkbox>
          </li>
          <li>
            <Checkbox
              name="status"
              value="on_auction"
              defaultChecked={status.includes('on_auction')}
            >
              On Auction
            </Checkbox>
          </li>
        </ul>
      </Form>
    </Panel>
    <Panel header="Price" key="price">
      <Form name="search" action='/search' method="get">
        <Select
          name="blockchain"
          value={
            blockchain
              ? options.filter((a) => a.value === blockchain)
              : undefined
          }
          options={options}
          placeholder="Blockchain"
          type="white"
        />
        <div className="d-flex align-center price">
          <TextInput
            value={min ? min : undefined}
            name="min"
            placeholder="Min"
          />
          <span>to</span>
          <TextInput
            value={max ? max : undefined}
            name="max"
            placeholder="Max"
          />
        </div>
        <button
          onClick={(e) => {
            e.stopPropagation()
            submit(e.currentTarget, { replace: false })
          }}
          className="btn primary-btn btn-lg w-100"
        >
          Apply
        </button>
      </Form>
    </Panel>

我如何解决这个问题以获得所有参数,而不必使用 React 状态自行管理它们?

编辑:- 我希望第一个过滤器自动提交,而后者在单击按钮时提交。

我想要实现的 UI 一点点,

答案:在投入了足够的时间寻找捷径后,终于明白这不是remix.run的神奇之处。使用 formik 之类的东西并比较地更新状态。

当您提交表单时,包含的唯一值是提交表单下的值。不包括任何其他形式的值(幸运的是!)。

所以我会使用一个表单,其中包含所有输入(复选框和文本输入)。 然后,您可以在复选框上添加类似 onChange 处理程序的东西,而不是表单上的 onChange 并在内部强制提交表单(使用 ref 单击提交按钮或其他东西,我认为使用在表单上引用您需要在提交函数中提交所有值,因此单击引用按钮可能更简单)。

请记住,如果您想在提交后“恢复”字段值,您需要像这样从加载程序函数中 return 它们:

// Loader function
 const url = new URL(request.url);

 return {
  results: [...], 
  values: Object.fromEntries(url.searchParams.entries())
 };

然后在组件中,使用values from useLoaderData:

<input type="text" name="max" defaultValue={values.max || ""}/>

额外的好处:如果您返回此页面(例如通过单击浏览器返回),您的搜索参数和搜索结果仍然存在!

我实际上为你准备了一个 stackblitz,但我丢失了所有更改:(

您似乎可以将所有字段保存在一个表单中,然后在按下提交按钮时提交该表单。

然后 onChange,检查目标名称是否为 'status',并提交表单。

export default function App() {
  const submit = (form) => {
    form.submit();
  };

  return (
    <form
      name="search"
      action="/search"
      method="get"
      onChange={(e) => {
        if (e.target.name === "status") {
          submit(e.currentTarget);
        }
      }}
    >
      <fieldset>
        <legend>status</legend>
        <label>
          <input type="checkbox" name="status" value="buy_now" />
          buy_now
        </label>
        <label>
          <input type="checkbox" name="status" value="on_auction" />
          on_auction
        </label>
      </fieldset>

      <fieldset>
        <legend>price</legend>

        <label>
          <div>blockchain</div>
          <select name="blockchain">
            <option value="option_1">Blockchain Option 1</option>
            <option value="option_2">Blockchain Option 2</option>
          </select>
        </label>
        <label>
          min <input type="number" name="min" />
        </label>
        <label>
          max <input type="number" name="max" />
        </label>
      </fieldset>
      <button type="submit">Apply</button>
    </form>
  );
}

demo

注意:不确定您想要将其分成不同形式的动机是什么,但我认为您指的 magic 是服务器状态、URLSearchParams、FormData和 UI 都是一致的,因为它们使用相同的基础数据,仅使用通用的 Web API。