reactjs - Jag kan inte lista ut hur jag lägger till Typescript till mina React useState-hookar, vad gör jag fel?


Jag har haft många problem med att lägga till Typescript i min React-kod, speciellt med useState-hooks.

Jag har tillbringat de senaste dagarna med att granska hur man åtgärdar detta, men jag är osäker på vad som behöver skickas in i hooksen. Bör jag skapa en separat .ts-fil för att lagra det jag förväntar mig i hooksen? När jag hovrar över de understrukna felen, fortsätter det att visa fel som:

Argument av typ 'Map' kan inte tilldelas parameter av typen 'SetStateAction'. Typen 'Map' matchar inte signaturen '(prevState: undefined): undefined'.

eller

Egenskapen 'features' finns inte på typen '{ children?: ReactNode; }`.

Jag har inkluderat min kod för att ge en bättre inblick och lämnat kvar kommentarerna från källan jag använder.

import { FC } from "react";
import { useState, useEffect, useRef } from "react";
import "./mapwrapper.css";

// openlayers
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import XYZ from "ol/source/XYZ"; //here...

import { fromLonLat } from "ol/proj";

const Home: FC<{}> = (props) => {
  // set intial state
  const [map, setMap] = useState();
  const [featuresLayer, setFeaturesLayer] = useState();

  // pull refs
  const mapElement = useRef<HTMLDivElement>(null);

  // create state ref that can be accessed in OpenLayers onclick callback function
  //  https://stackoverflow.com/a/60643670
  const mapRef = useRef<{}>();
  mapRef.current = map;

  // initialize map on first render - logic formerly put into componentDidMount
  useEffect(() => {
    // create and add vector source layer
    const initalFeaturesLayer = new VectorLayer({
      source: new VectorSource(),
    });

    const seoul = [126.97794, 37.56629];
    const seoulWebMercator = fromLonLat(seoul);

    // create map
    const initialMap = new Map({
      target: mapElement.current!,
      layers: [

        // Google Maps Terrain
        new TileLayer({
          source: new XYZ({
            url: "http://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}",
          }),
        }),

        initalFeaturesLayer,
      ],
      view: new View({
        projection: "EPSG:3857",
        center: seoulWebMercator,
        zoom: 16,
      }),
      controls: [],
    });

    // save map and vector layer references to state
    setMap(initialMap);
    setFeaturesLayer(initalFeaturesLayer);
  }, []);

  // update map if features prop changes - logic formerly put into componentDidUpdate
  useEffect(() => {
    if (props.features.length) {
      // may be null on first render

      // set features to map
      featuresLayer.setSource(
        new VectorSource({
          features: props.features, // make sure features is an array
        })
      );

      // fit map to feature extent (with 100px of padding)
      map.getView().fit(featuresLayer.getSource().getExtent(), {
        padding: [100, 100, 100, 100],
      });
    }
  }, [props.features, featuresLayer, map]);


  return (
    <div>
      <div ref={mapElement} className="map-container"></div>

    </div>
  );
};

export default Home;

Svar #1

För kartproblemet bör du ange typen uttryckligen

const [map, setMap] = useState<Map>();

För problem med feature och featureLayer bör du ange props-typen

type HomeProps = { features: any[] };

const Home: FC<HomeProps> = (props) => {

 const [map, setMap] = useState<Map>();
 const [featuresLayer, setFeaturesLayer] = useState<
    VectorLayer<VectorSource<Geometry>>
 >();


 ...

 useEffect(() => {
    if (props.features?.length && featuresLayer) {
    ...
    }
 }, [props.features, featuresLayer, map]);
  
}

Här är codesandbox för demo

Svar #2

I TypeScript måste du deklarera alla typer, inklusive alla egenskaper inne i en objekttyp.

Från de felmeddelanden du gav är de två felen eftersom du inte deklarerade rätt typ.

Argument av typ 'Map' kan inte tilldelas parameter av typen 'SetStateAction'. Typen 'Map' matchar inte signaturen '(prevState: undefined): undefined'.

Detta fel uppstår eftersom du inte deklarerade en typ för useState, så den sätts som standard till undefined. Du kan enkelt åtgärda det genom att göra något sådant här:

// You should substitute `any` type to a more appropriate type.
const [map, setMap] = useState<Map<any, any>>();

Egenskapen 'features' finns inte på typen '{ children?: ReactNode; }`.

Detta fel beror på att du inte deklarerade de egenskaper som krävs i typen för komponentegenskaper.

type HomeProps = {
  // You should substitute `any` type to a more appropriate type.
  features: any;
};

const Home: FC<HomeProps> = (props) => {
  ...
}

Det finns förmodligen fler liknande fel där du inte deklarerade typerna korrekt. Allt du behöver göra är att deklarera dem.