简体   繁体   English

我已经用 typescript 对自定义挂钩错误做出反应

[英]i have react custom hook error with typescript

I have this error in VScode: Argument of type 'Animal[]' is not assignable to parameter of type 'string'.我在 VScode 中有这个错误:'Animal[]' 类型的参数不可分配给'string' 类型的参数。 my custom hook file(useLocalHost.tsx) is:我的自定义挂钩文件(useLocalHost.tsx)是:

import React, { useState, useEffect, SetStateAction, Dispatch } from "react";
import { Animal } from "@frontendmasters/pet";

function getSavedValue(key: string, initialValue: string) {
  
  const savedValue = JSON.parse(localStorage.getItem(key) || '{}');

  if (savedValue) {
    return savedValue;
  }

  return initialValue;
}

export default function useLocalStorage(key: string, initialValue: string) {
  const [value, setValue] = useState(() => {
    return getSavedValue(key, initialValue);
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [value]);
  return [value, setValue] as [Animal[], Dispatch<SetStateAction<Animal[] | null>>];
}

my search file (searchParams.tsx) is:我的搜索文件(searchParams.tsx)是:

import React, { useState, useEffect, useContext, FunctionComponent } from "react";
import pet, { ANIMALS, Animal } from "@frontendmasters/pet";
import useDropdown from "./useDropdown";
import { RouteComponentProps } from '@reach/router';
import SearchResult from "./SearchResult";
import useLocalStorage from "./useLocalStorage";
import ThemeContext from "./ThemeContext";

const SearchParams: FunctionComponent<RouteComponentProps> = () => {
  const [location, updateLocation] = useState("Seattle, WA");
  const [breeds, updateBreeds] = useState([] as string[]);
  const [pets, updatePets] = useState([] as Animal[]);
  const [animal, AnimalDropdown] = useDropdown("Animal", "dog", ANIMALS);
  const [breed, BreedDropdown, updateBreed] = useDropdown("Breed", "", breeds);
  const [prevPet, setPrevPet] = useLocalStorage([] as Animal[], "");
  const [theme, setTheme] = useContext(ThemeContext);

  async function requestPets() {
    const { animals } = await pet.animals({
      location,
      breed,
      type: animal,
    });
    setPrevPet(animals);
    updatePets(animals || []);
  }

  useEffect(() => {
    updateBreeds([]);
    updateBreed("");
    pet.breeds(animal).then(({ breeds }) => {
      const breedStrings = breeds.map(({ name }) => name);
      updateBreeds(breedStrings);
    }, console.error);
  }, [animal]);

  useEffect(() => {
    updatePets(prevPet);
  }, []);

I know that the error comes from the type of prevPet put I don't know what type it should be there is more in searchParams.tsx but I think it's not needed我知道错误来自 prevPet 的类型我不知道它应该是什么类型 searchParams.tsx 中有更多但我认为不需要

Your getSavedValue function has bugs in it.您的getSavedValue function 中有错误。

const savedValue = JSON.parse(localStorage.getItem(key) || '{}');

I think this should be我认为这应该是

const savedValue = JSON.parse(localStorage.getItem(key) || {});

Otherwise the return type of your function can be an object or a string (when nothing was in the storage).否则,您的 function 的返回类型可以是 object 或字符串(当存储中没有任何内容时)。

Also, savedValue will never be falsy, so you will never return initialValue .此外, savedValue永远不会是虚假的,所以你永远不会返回initialValue

Moreover, you call the hook with the params in the wrong order.此外,您以错误的顺序调用带有参数的钩子。

Here is a typed alternative:这是一个类型化的替代方案:

import React, { useState, useEffect } from "react";

function getSavedValue<T>(key: string, initialValue: T): T {
  const stored = localStorage.getItem(key);

  if (stored) {
    return JSON.parse(stored) as T;
  }

  return initialValue;
}

export default function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => getSavedValue(key, initialValue));

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [value]);
  
  return [value, setValue] as const;
}

You can use it like this:你可以像这样使用它:

const [prevPet, setPrevPet] = useLocalStorage<Animal[]>("key", []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM