0

我正在开发一个搜索 UI,其中有很多过滤器,当有人选择/检查选项时,我希望这些过滤器作为 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 状态自己管理它们?

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

我想要实现的一些用户界面,

在此处输入图像描述

答:花了足够的时间寻找捷径之后,终于明白这不是 remix.run 的魔法之一。使用 formik 之类的东西并彻底更新状态。

4

2 回答 2

1

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

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

请记住,如果您想在提交后“恢复”字段值,则需要从加载器函数中返回它们,如下所示:

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

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

然后在组件中,使用valuesfrom useLoaderData

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

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

实际上,我为您设置了一个堆栈闪电战,但我丢失了所有更改:(

于 2022-02-03T13:31:05.187 回答
0

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

然后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>
  );
}

演示

注意:不确定您想要将其分成单独的表单的动机是什么,但我认为您所指的魔法是服务器状态、URLSearchParams、FormData 和 UI 都是对齐的,因为它们使用相同的底层数据,仅使用常见的 Web API。

于 2022-02-05T02:54:28.000 回答