Fable: Diseño de la API auxiliar de React

Creado en 19 mar. 2016  ·  3Comentarios  ·  Fuente: fable-compiler/Fable

Actualmente estoy diseñando una API para facilitar la interacción con React de F# y la combinación de idiomas ofrece varias oportunidades interesantes para la verificación estática. Sin embargo, como era de esperar, hay algunas asperezas y tengo dudas sobre cómo definir las propiedades en un elemento React DOM. Actualmente tenemos:

Opción 1 : propiedades dinámicas

module R = Fable.ReactHelper
R.input [
    "type" ==> "text"
    "placeholder" ==> "Your name"
    "value" ==> x.state.author
    "onChange" ==> x.handleAuthorChange
] []

Esta es la opción más flexible ya que podemos pasar cualquier propiedad en un objeto JS simple. Gracias a las funciones de inserción, no necesitamos usar createObj aquí y también ahorramos algunas llaves. Si cree que ==> es demasiado detallado, acortar también es trivial: let inline (=>) a b = a ==> b

El problema es que no tenemos ninguna verificación estática o finalización automática para las propiedades. Así que estoy considerando usar una lambda en su lugar. Pero ahora tenemos que decidir de dónde sacar la firma. Al principio tomé el de IntrinsicElements definido en el archivo de definición de React :

Opción 2 : mutar las propiedades de HTMLElement

R.input (fun p ->
    p.``type`` <- "text"
    p.placeholder <- "Your name"
    p.value <- unbox x.state.author
    //p.onchange <- unbox x.handleAuthorChange
    p?onChange <- x.handleAuthorChange
) []           

Ahora tenemos verificación estática y finalización automática para las propiedades, lo cual es muy bueno. Sin embargo, tenga en cuenta que algunas fricciones con las definiciones de tipo comienzan a aparecer y deben resolverse con unbox . El mayor problema con este enfoque es que, aunque la definición de TypeScript usa los elementos DOM estándar, algunos atributos tienen una ortografía diferente en React. En el ejemplo anterior, configurar onchange no funcionará, por lo que debemos configurar onChange dinámicamente. Esto casi rompe todos los beneficios de la comprobación estática :(

Nuestra próxima opción entonces es usar React.HTMLAttributes en

Opción 3 : mutar las propiedades de React.HTMLAttributes

R.input (fun p ->
    p.``type`` <- Some "text"
    p.placeholder <- Some "Your name"
    p.value <- unbox x.state.author
    p.onChange <- unbox x.handleAuthorChange
) []

Bien, todas las propiedades tienen la ortografía que React espera, pero ahora enfrentamos otros problemas: primero, las fricciones con la firma se multiplican porque todas las propiedades se definen como opcionales y otros elementos personalizados de TypeScript se usan como tipos de unión borrados o funciones personalizadas; y segundo, en la opción anterior teníamos los atributos específicos para las etiquetas input pero aquí todos los elementos HTML comparten los mismos atributos. Sin embargo, esta puede seguir siendo la mejor opción.

Habría una cuarta opción pero no la estoy considerando mucho:

Opción 4 : usar un registro HTMLAttributes personalizado

R.input (fun p ->
    { p with
        ``type`` = Some "text"
        placeholder = Some "Your name"
        value = unbox x.state.author
        onChange = unbox x.handleAuthorChange
}) []

Es probable que este sea el más idiomático en F#, pero las reglas de sangría se vuelven más complicadas ( { p with no se puede poner en la primera línea) y no tenemos autocompletado aquí para descubrir las propiedades de p , que yo sepa. Lo que es más importante, adoptar este estilo requeriría crear un registro personalizado por HTMLAttributes ya que los de TypeScript se analizan como interfaces (hay buenas razones para ello), por lo que esto agregaría un paso adicional en el mantenimiento de Fable Archivo

Estas son las opciones para tomar la decisión y me encantaría escuchar su opinión al respecto. Sé que es posible agregar varias opciones a la API, pero esto probablemente lo haría más confuso para los recién llegados y preferiría hacerlo simple al principio. ¡Muchas gracias por su ayuda de antemano!

discussion

Comentario más útil

Opción 5.
Amplíe la opción 1. para agregar atributos escritos. Estaba haciendo una API similar para FunScript en el pasado.
https://github.com/FractalProject/Fractal.Sample/blob/master/client/App.fsx#L65 -L74
https://github.com/FractalProject/Fractal/blob/master/src/Fractal.DOM.fs

Opción 6.
Vuélvase súper loco y cree una expresión computacional con palabras clave personalizadas.

Todos 3 comentarios

Opción 5.
Amplíe la opción 1. para agregar atributos escritos. Estaba haciendo una API similar para FunScript en el pasado.
https://github.com/FractalProject/Fractal.Sample/blob/master/client/App.fsx#L65 -L74
https://github.com/FractalProject/Fractal/blob/master/src/Fractal.DOM.fs

Opción 6.
Vuélvase súper loco y cree una expresión computacional con palabras clave personalizadas.

Para los recién llegados, creo que la Opción 4 parece ser la mejor, además no tiene cadenas mágicas y mantiene las cosas inmutables.

¡Gracias por la sugerencia, @Krzysztof-Cieslak! Al principio tenía miedo de que esto requiriera más trabajo de mantenimiento, pero después de considerarlo me di cuenta de que esta era la mejor opción. Me basé en su código y escribí un script para generar (parcialmente) el módulo auxiliar:
https://github.com/fsprojects/Fable/blob/master/samples/browser/react/public/Fable.ReactHelper.fs

El código de renderizado es mucho más bonito ahora con una verificación estática completa :)
https://github.com/fsprojects/Fable/blob/master/samples/browser/react/public/components.fs#L104 -L124

Todavía hay trabajo por hacer en React Helper, pero estoy cerrando el problema por ahora. ¡Gracias por toda tu ayuda!

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

jwosty picture jwosty  ·  3Comentarios

krauthaufen picture krauthaufen  ·  3Comentarios

tomcl picture tomcl  ·  4Comentarios

forki picture forki  ·  3Comentarios

MangelMaxime picture MangelMaxime  ·  3Comentarios