reactjs - qué - Valor de propiedad predeterminado en React componente usando TypeScript
react js ejemplos (5)
Accesorios predeterminados con componente de clase
El uso de
static defaultProps
es correcto.
También debe usar interfaces, no clases, para los accesorios y el estado.
Actualización 2018/12/1
: TypeScript ha mejorado la verificación de tipos relacionada con
defaultProps
a
defaultProps
largo del tiempo.
Siga leyendo para conocer el uso más reciente y mejor hasta usos y problemas más antiguos.
Para TypeScript 3.0 y superior
TypeScript
agregó
específicamente
soporte para
defaultProps
para hacer que la verificación de tipos funcione como es de esperar.
Ejemplo:
interface PageProps {
foo: string;
bar: string;
}
export class PageComponent extends React.Component<PageProps, {}> {
public static defaultProps = {
foo: "default"
};
public render(): JSX.Element {
return (
<span>Hello, { this.props.foo.toUpperCase() }</span>
);
}
}
Que se puede procesar y compilar sin pasar un atributo
foo
:
<PageComponent bar={ "hello" } />
Tenga en cuenta que:
-
foo
no está marcado como opcional (es decir,foo?: string
) aunque no se requiere como un atributo JSX. Marcar como opcional significaría que podría estarundefined
, pero en realidad nunca estaráundefined
porquedefaultProps
proporciona un valor predeterminado. Piénselo de forma similar a cómo puede marcar un parámetro de función opcional, o con un valor predeterminado, pero no ambos, pero ambos significan que la llamada no necesita especificar un valor . TypeScript 3.0+ tratadefaultProps
de manera similar, ¡lo cual es realmente genial para los usuarios de React! -
defaultProps
no tiene una anotación de tipo explícito. Su tipo es inferido y utilizado por el compilador para determinar qué atributos JSX son necesarios. Puede usardefaultProps: Pick<PageProps, "foo">
para asegurarse de quedefaultProps
coincida con un subconjunto dePageProps
. Más sobre esta advertencia se explica aquí . -
Esto requiere
@types/react
versión16.4.11
para funcionar correctamente.
Para TypeScript 2.1 hasta 3.0
Antes de que TypeScript 3.0 implementara la compatibilidad con el compilador para
defaultProps
, todavía podía usarlo, y funcionaba al 100% con React en tiempo de ejecución, pero dado que TypeScript solo consideraba los accesorios al verificar los atributos JSX, tendría que marcar los accesorios que tienen valores predeterminados como opcionales con
?
.
Ejemplo:
interface PageProps {
foo?: string;
bar: number;
}
export class PageComponent extends React.Component<PageProps, {}> {
public static defaultProps: Partial<PageProps> = {
foo: "default"
};
public render(): JSX.Element {
return (
<span>Hello, world</span>
);
}
}
Tenga en cuenta que:
-
Es una buena idea anotar
defaultProps
conPartial<>
para que compruebe los tipos con sus accesorios, pero no tiene que proporcionar a cada propiedad requerida un valor predeterminado, lo que no tiene sentido ya que las propiedades requeridas nunca deberían necesitar un valor predeterminado. -
Cuando se utiliza
strictNullChecks
el valor dethis.props.foo
possibly undefined
estarápossibly undefined
y requerirá una aserción no nula (es decir,this.props.foo!
) O type-guard (es decir,if (this.props.foo) ...
) para eliminarundefined
Esto es molesto ya que el valor de apoyo predeterminado significa que en realidad nunca será indefinido, pero TS no entendió este flujo. Esa es una de las razones principales por las que TS 3.0 agregó soporte explícito paradefaultProps
.
Antes de TypeScript 2.1
Esto funciona igual pero no tiene tipos
Partial
, por lo tanto, omita
Partial<>
y proporcione los valores predeterminados para todos los accesorios necesarios (aunque esos valores predeterminados nunca se usarán) u omita la anotación de tipo explícito por completo.
Accesorios predeterminados con componentes funcionales
También puede usar
defaultProps
en los componentes de la función, pero debe escribir su función en la interfaz
StatelessComponent
(
FunctionComponent
en
@types/react
versión
16.7.2
+) para que TypeScript conozca
defaultProps
en la función:
interface PageProps {
foo?: string;
bar: number;
}
const PageComponent: StatelessComponent<PageProps> = (props) => {
return (
<span>Hello, {props.foo}, {props.bar}</span>
);
};
PageComponent.defaultProps = {
foo: "default"
};
Tenga en cuenta que no tiene que usar
Partial<PageProps>
ningún lugar porque
StatelessComponent.defaultProps
ya está especificado como parcial en TS 2.1+.
Otra buena alternativa (esto es lo que uso) es desestructurar los parámetros de sus
props
y asignar valores predeterminados directamente:
const PageComponent: StatelessComponent<PageProps> = ({foo = "default", bar}) => {
return (
<span>Hello, {foo}, {bar}</span>
);
};
¡Entonces no necesitas los
defaultProps
en absoluto!
Tenga en cuenta que si proporciona
defaultProps
en un componente de función, tendrá prioridad sobre los valores de parámetros predeterminados, porque React siempre pasará explícitamente los valores de
defaultProps
(por lo que los parámetros nunca están indefinidos, por lo tanto, el parámetro predeterminado nunca se usa). d usar uno u otro, no ambos.
No puedo encontrar la manera de establecer valores de propiedad predeterminados para mis componentes usando Typecript.
Este es el código fuente:
class PageState
{
}
export class PageProps
{
foo: string = "bar";
}
export class PageComponent extends React.Component<PageProps, PageState>
{
public render(): JSX.Element
{
return (
<span>Hello, world</span>
);
}
}
Y cuando trato de usar el componente así:
ReactDOM.render(<PageComponent />, document.getElementById("page"));
Me sale un error diciendo que falta la propiedad
foo
.
Quiero usar el valor predeterminado.
También he intentado usar
static defaultProps = ...
dentro del componente, pero no tuvo ningún efecto, como sospechaba.
src/typescript/main.tsx(8,17): error TS2324: Property ''foo'' is missing in type ''IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...''.
¿Cómo puedo usar los valores de propiedad predeterminados? Muchos componentes de JS que usa mi compañía dependen de ellos y no usarlos no es una opción.
Con Typecript 2.1+, use Parcial <T> en lugar de hacer que las propiedades de su interfaz sean opcionales.
export interface Props {
obj: Model,
a: boolean
b: boolean
}
public static defaultProps: Partial<Props> = {
a: true
};
Con Typecript 3.0 hay una nueva solución para este problema:
export interface Props {
name: string;
}
export class Greet extends React.Component<Props> {
render() {
const { name } = this.props;
return <div>Hello ${name.toUpperCase()}!</div>;
}
static defaultProps = { name: "world"};
}
// Type-checks! No type assertions needed!
let el = <Greet />
Tenga en cuenta que para que esto funcione, necesita una versión más nueva de
@types/react
que
16.4.6
.
Funciona con
16.4.11
.
De un comentario de @pamelus sobre la respuesta aceptada:
Debe hacer que todas las propiedades de la interfaz sean opcionales (incorrectas) o especificar el valor predeterminado también para todos los campos obligatorios (repetitivo innecesario) o evitar especificar el tipo en defaultProps.
En realidad, puede usar la herencia de interfaz de Typecript . El código resultante es solo un poco más detallado.
interface OptionalGoogleAdsProps {
format?: string;
className?: string;
style?: any;
scriptSrc?: string
}
interface GoogleAdsProps extends OptionalGoogleAdsProps {
client: string;
slot: string;
}
/**
* Inspired by https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js
*/
export default class GoogleAds extends React.Component<GoogleAdsProps, void> {
public static defaultProps: OptionalGoogleAdsProps = {
format: "auto",
style: { display: ''block'' },
scriptSrc: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
};
Para aquellos que tienen accesorios opcionales que necesitan valores predeterminados. Crédito aquí :)
interface Props {
firstName: string;
lastName?: string;
}
interface DefaultProps {
lastName: string;
}
type PropsWithDefaults = Props & DefaultProps;
export class User extends React.Component<Props> {
public static defaultProps: DefaultProps = {
lastName: ''None'',
}
public render () {
const { firstName, lastName } = this.props as PropsWithDefaults;
return (
<div>{firstName} {lastName}</div>
)
}
}