我已经用打字稿反应了自定义钩子错误

时间:2020-07-27 15:52:54

标签: reactjs typescript

我在VScode中出现此错误: “ Animal []”类型的参数不能分配给“ string”类型的参数。 我的自定义挂钩文件(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>>];
}

我的搜索文件(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);
  }, []);

我知道错误来自prevPet类型,我不知道应该是哪种类型 searchParams.tsx中有更多内容,但我认为不需要

1 个答案:

答案 0 :(得分:0)

您的getSavedValue函数中存在错误。

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

我认为应该是

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

否则,函数的返回类型可以是对象或字符串(当存储中没有任何内容时)。

此外,savedValue永远不会虚假,因此您永远不会返回initialValue

此外,您用错误的顺序调用带有参数的钩子。

这是类型化的替代项:

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;
}

您可以像这样使用它:

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