数据验证器

在 QwikCity 中,数据验证器对于验证请求事件和动作、加载器的数据是必不可少的。这些验证在执行相关的动作或加载器之前在服务器端进行。与 zod$() 函数类似,Qwik 提供了一个专用的 validator$() 函数来实现这个目的。

import {
  type RequestEvent,
  type RequestEventAction,
  routeAction$,
  validator$,
} from "@builder.io/qwik-city";
 
export const useAction = routeAction$(
  async (data, requestEvent: RequestEventAction) => {
    return { foo: "bar" };
  },
  validator$(async (ev: RequestEvent, data) => {
    if (ev.query.get("secret") === "123") {
      return { success: true };
    }
    return {
      success: false,
      error: {
        message: "secret is not correct",
      },
    };
  }),
);

当向 routeAction() 提交请求时,请求事件和数据会根据定义的验证器进行验证。如果验证失败,动作将在 routeAction.value 属性中放置验证错误。

export default component$(() => {
  const action = useAction();
 
  // 在提交之前,动作的值是 undefined
  if (action.value) {
    if (action.value.failed) {
      // 如果查询字符串没有 secret,则动作失败
      action.value satisfies { failed: true; message: string };
    } else {
      action.value satisfies { searchResult: string };
    }
  }
 
  return (
    <button onClick$={() => action.submit({ search: "foo" })}>提交</button>
  );
});

多个验证器

动作和加载器可以有多个验证器,它们按照相反的顺序执行。在下面的示例中,验证器的执行顺序是 validator3 -> validator2 -> validator1

const validator1 = validator$(/*...*/)
const validator2 = validator$(/*...*/)
const validator3 = validator$(/*...*/)
 
export const useAction = routeAction$(
  async (data, requestEvent: RequestEventAction) => {
    return { foo: "bar" };
  },
  validator1,
  validator2,
  validator3, // 将首先执行
);

如果 validator3 在其成功返回对象中有一个 data 属性,这个数据将传递给下一个验证器 validator2。如果你不想覆盖原始提交的数据,请避免将 data 属性放在成功返回对象中。

export const useAction = routeAction$(
  async (data, requestEvent: RequestEventAction) => {
    console.log(data); // { message: "hi, I am validator1" }
    return { foo: "bar" };
  },
  // validator1
  validator$((ev, data) => {
    console.log(data); // { message: "hi, I am validator2" }
    return {
      success: true,
      data: {
        message: "hi, I am validator1",
      },
    };
  }),
  // validator2
  validator$((ev, data) => {
    console.log(data); // { message: "hi, I am validator3" }
    return {
      success: true,
      data: {
        message: "hi, I am validator2",
      },
    };
  }),
  // validator3
  validator$((ev, data) => {
    console.log(data); // 您提交的数据
    return {
      success: true,
      data: {
        message: "hi, I am validator3",
      },
    };
  }),
);

返回对象

数据验证器在其返回对象中期望特定的属性。

验证成功

对于成功的验证,success 属性必须为 true。

interface Success {
  success: true;
  data?: any;
}

验证失败

interface Fail {
  success: false;
  error: Record<string, any>;
  status?: number;
}

当验证器返回一个失败的对象时,它的行为类似于在动作或加载器中使用 fail() 方法。

const status = 500;
const errorObject = { message: "123" };
 
export const useAction = routeAction$(
  async (_, { fail }) => {
    return fail(status, errorObject);
  },
  validator$(async () => {
    return {
      success: false,
      status,
      errorObject,
    };
  }),
);

在动作中同时使用 validator$()zod$()

对于动作来说,类型化的数据验证器 zod$() 应该是 routeAction$ 的第二个参数,后面是其他的数据验证器 validator$()

export const useAction = routeAction$(
  async (data, requestEvent: RequestEventAction) => {
    return { foo: "bar" };
  },
  zod$(/*...*/),
  validator$(/*...*/),
  validator$(/*...*/),
);

Contributors

Thanks to all the contributors who have helped make this documentation better!

  • wtlin1228
  • harishkrishnan24