【问题标题】:React hook / render difficulties反应钩子/渲染困难
【发布时间】:2020-06-03 12:12:02
【问题描述】:

我正在使用带有 typescript 和非常严格的 eslint 配置的 next.js。我对你将如何解决这个问题很感兴趣。

用例: 我想获取数据客户端。一旦数据在那里,我想显示它。挺容易。

现在问题来了。

如果我将 useEffectHook 放在 if(!data) 块上方,我会得到“TypeError: filterVaccinationsBy is not a function”

如果我在 if(!data) 块下使用我的 useEffectHook,我会收到“错误:渲染的钩子比上一次渲染期间更多。”

你如何解决这些问题?

谢谢!!

    const MyPage: any = (props: { AuthUserInfo: any }) => {
  const [vaccinationList, setVaccinationList] = useState<
    IVaccination[] | undefined
  >(undefined);
  const [filter, setFilter] = useState<
    "noFilter" | "travel" | "children" | "gratis" | "combination"
  >("noFilter");

  const { data, error } = useRequest<Vaccinations>(
    VACCINATIONS_QUERY,
    (query: any) => graphQLClient.request<Vaccinations>(query)
  );

  const changeFilterOrder = (vaccinations: IVaccination[] | undefined) => {
    if (filterOrder === "alphabetical") {
      console.log("in alphabetical filtering");

      const alphabeticalOrder = vaccinations?.sort((a, b) =>
        a.name.localeCompare(b.name)
      );
      return alphabeticalOrder;
    }
    if (filterOrder === "chronological") {
      console.log("in chronological filtering");
      const chronologicalOrder = _.sortBy(vaccinations, [
        function (vacc) {
          return vacc.vacc_start_weeks;
        },
      ]);
      return chronologicalOrder;
    }
  };

  useEffect(() => {
    filterVaccinationsBy("noFilter");
  }, []);

  if (!data) {
    return <p>Loading data...</p>;
  }

  if (error) {
    return <p>Error: {JSON.stringify(error)}</p>;
  }
  const { multivaccination, vaccination } = data;

  const mergedList = vaccination.map(
    ({
      id,
      name,
      description,
      vacc_start_weeks,
      vacc_start_text,
      vaccination_vaccination_plan,
    }) => ({
      id,
      name,
      description,
      vacc_start_weeks,
      vacc_start_text,
      vaccination_vaccination_plan,
      multivaccinationByMultivaccination: multivaccination
        .filter((multivacc) => multivacc.parent_id === id)
        .map(({ vaccinations }) => vaccinations),
    })
  );

  const filterVaccinationsBy = (filterBy: string) => {
    if (filterBy === "travel") {
      setFilter("travel");
      const travelVaccinations = mergedList.filter(
        (vacc: IVaccination) =>
          vacc.vaccination_vaccination_plan[0]?.vaccination_plan &&
          vacc.vaccination_vaccination_plan[0]?.vaccination_plan.target_group?.includes(
            "travel"
          )
      );
      const correctOrder = changeFilterOrder(travelVaccinations);
      setVaccinationList(correctOrder);
    }
    if (filterBy === "gratis") {
      setFilter("gratis");
      const gratisVaccinations = mergedList.filter(
        (vacc: IVaccination) =>
          vacc.vaccination_vaccination_plan[0].vaccination_plan?.dose1_price ===
          0
      );
      const correctOrder = changeFilterOrder(gratisVaccinations);
      setVaccinationList(correctOrder);
    }
    if (filterBy === "children") {
      setFilter("children");
      const childrenVaccinations = mergedList.filter(
        (vacc: IVaccination) =>
          vacc.vaccination_vaccination_plan[0].vaccination_plan &&
          vacc.vaccination_vaccination_plan[0].vaccination_plan.target_group?.includes(
            "children"
          )
      );
      const correctOrder = changeFilterOrder(childrenVaccinations);
      setVaccinationList(correctOrder);
    }
    if (filterBy === "combination") {
      setFilter("combination");
      const combinationVaccinations = mergedList.filter(
        (vacc: IVaccination) =>
          vacc.multivaccinationByMultivaccination.length > 0
      );
      const correctOrder = changeFilterOrder(combinationVaccinations);
      setVaccinationList(correctOrder);
    }
    if (filterBy === "noFilter") {
      setFilter("noFilter");
      const correctOrder = changeFilterOrder(mergedList);
      console.log("1");
      setVaccinationList(correctOrder);
      console.log("2");
    }
  };

  return (<p>Hey beautiful<p> )

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    你的 useEffect 不能在你的 if(!data) 下,因为你的功能组件会在那个时候返回并且永远不会调用 useEffect。反应文档比我解释得更好,但你不能做条件挂钩!必须始终调用钩子!

    我认为您得到“TypeError:filterVaccinationsBy 不是函数”,因为调用时未定义 filterVaccinationsBy。将函数声明放在 useEffect 上面,或者将其转换为非箭头/标准函数。

    【讨论】:

    • 我不能把它放在 useEffect 上面,因为我需要函数中的数据,这些数据只有在获取后才会被填充。我正在寻求最佳实践... :) 更改箭头函数也无济于事,因为 ESLint 仍在抱怨我在声明之前使用 ah 函数...
    • 首先,eslint 不是神,它是清洁代码的指南,您可以随时禁用文件/行的规则。其次,如果您的函数取决于数据,最好将其作为函数的参数传递,而不是使用范围。它被称为“纯函数”。可以在组件之外定义纯函数。
    • 对不起。我得到一个 typeError 以及固定的 eslint 错误: TypeError: filterVaccinationsBy is not a function。我无法传入数据,因为它还没有加载。
    猜你喜欢
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多