react router - problem med typer når man bruker "withRouter" og Typescript
Jeg prøver å få litt mer dyp kunnskap og praksis i React+Typescript, og jeg har støtt på denne typefeilen når jeg bruker withRouter fra react-router-dom.
Kodeeksemplet mitt er veldig enkelt, og jeg har forsøkt å finne personer med samme problem, og noen av svarene pekte på en feil med en oppgradering (men de var fra 2016, så...) og noen av dem brukte en connect()-setning som jeg ikke bruker (noe som førte til spørsmålet, "Gjør jeg dette feil fordi jeg ikke bruker det?"). Jeg ser at noen av de forslagene også involverte å mappe Props til State, noe jeg ikke har gjort (eller sett) før nå. Jeg håper noen har forslag til hva jeg mangler og hva annet jeg bør se på.
Koden er:
import React from "react";
import { withRouter } from "react-router-dom";
interface ISection {
id: number;
title: string;
imageUrl: string;
size: string;
}
class MenuItem extends React.Component<ISection> {
render() {
return (
<div className={`${this.props.size} menu-item`}>
<div
className="background-image"
style={{ backgroundImage: `url(${this.props.imageUrl})` }}
/>
<div className="content">
<h1 className="title">{this.props.title}</h1>
<span className="subtitle">some subtitle</span>
</div>
</div>
);
}
}
export default withRouter(MenuItem);
Det jeg ville forvente herfra er at det skal fungere smidig (jeg må si at jeg først prøvde med en funksjonell komponent siden jeg ikke har noen state, men alle løsningene jeg så involverte en klassekomponent, så jeg flyttet det inn i den), men i stedet får jeg følgende feil på MenuItem i siste linje:
Argument of type 'typeof MenuItem' is not assignable to parameter of type 'ComponentClass<RouteComponentProps<any, StaticContext, any>, any> | FunctionComponent<RouteComponentProps<any, StaticContext, any>> | (FunctionComponent<RouteComponentProps<any, StaticContext, any>> & ComponentClass<...>) | (ComponentClass<...> & FunctionComponent<...>)'.
Type 'typeof MenuItem' is not assignable to type 'ComponentClass<RouteComponentProps<any, StaticContext, any>, any>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'RouteComponentProps<any, StaticContext, any>' is missing the following properties from type 'Readonly<ISection>': id, title, imageUrl, sizets(2345)
Mine spørsmål er:
Hvorfor står det "type 'typeof MenuItem'"? Bør det ikke bare stå typen til 'MenuItem' i stedet for funksjonen for å få typen?
Er det nødvendig for at withRouter skal fungere med klassekomponenter, eller fungerer det også på funksjonelle komponenter?
Trenger jeg å
connect()noe, eller koble Props til State? Hvis ja, hvorfor?Og til slutt, hvordan kan jeg fikse dette?
Svar #1
Ifølge dokumentasjonen vil withRouter sende oppdaterte match, location og history props til den innpakkede komponenten hver gang den rendres.
Så MenuItem-komponenten bør ha props for å motta dem. Foreløpig har MenuItem-komponenten props av typen ISection, som ikke inkluderer router-props.
Den enkleste måten å legge til ruter-egenskaper på er å krysse ISection med RouteComponentProps.
import { withRouter, RouteComponentProps } from "react-router-dom";
// ...
class MenuItem extends React.Component<ISection & RouteComponentProps> {
Full kode er
import * as React from 'react';
import { withRouter, RouteComponentProps } from "react-router-dom";
interface ISection {
id: number;
title: string;
imageUrl: string;
size: string;
}
class MenuItem extends React.Component<ISection & RouteComponentProps> {
render() {
return (
<div className={`${this.props.size} menu-item`}>
<div
className="background-image"
style={{ backgroundImage: `url(${this.props.imageUrl})` }}
/>
<div className="content">
<h1 className="title">{this.props.title}</h1>
<span className="subtitle">some subtitle</span>
</div>
</div>
);
}
}
export default withRouter(MenuItem);
Og svar på dine spørsmål
Hvorfor står det "type 'typeof MenuItem'"? Bør det ikke bare stå typen til 'MenuItem' i stedet for funksjonen for å få typen?
Feil oppstått på grunn av typer som ikke er kompatible.
MenuItemer en klasse, ikke en type. For å få typen tilMenuItembør du bruketypeof MenuItem. Såtypeof MenuItemer en type. Og kompilatoren sier korrekt, "typetypeof MenuItem".Er det nødvendig for at withRouter skal fungere med klassekomponenter, eller fungerer det også på funksjonelle komponenter?
Det er tillatt å jobbe med klassekomponenter og med funksjonelle komponenter.
Slik vil komponenten din se ut hvis den implementeres som en funksjonell
const Cmp1: React.FunctionComponent<ISection & RouteComponentProps> = (props) => { return ( <div className={`${props.size} menu-item`}> <div className="background-image" style={{ backgroundImage: `url(${props.imageUrl})` }} /> <div className="content"> <h1 className="title">{props.title}</h1> <span className="subtitle">some subtitle</span> </div> </div> ); } const WrappedCmp = withRouter(Cmp1);Trenger jeg å
connect()noe, eller koble Props til State? Hvis ja, hvorfor?Nei, dette er ikke et strengt krav.
connecter en del av Redux, så hvis du bruker Redux kan du koble til. Her er dokumentasjonen på hvordan du brukerwithRoutermedconnect. Men igjen, det er ikke nødvendig.Og til slutt, hvordan kan jeg fikse dette?
Allerede besvart. Se over :-)
