-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve documentation how to create HOCs with Styles #53
Comments
For the record, here's how I do it: let private styles (theme: ITheme) : IStyles list =
Styles.Root [
CSSProp.BackgroundColor "red"
]
let private view' (classes: IClasses) model dispatch =
div [ HTMLAttr.Class !!classes?root ] []
// Boilerplate below to support JSS with Elmish
type private IProps =
abstract member model: Model with get, set
abstract member dispatch: (Msg -> unit) with get, set
inherit IClassesProps
type private Component(p) =
inherit PureStatelessComponent<IProps>(p)
let viewFun (p: IProps) = view' p.classes p.model p.dispatch
let viewWithStyles = withStyles (StyleType.Func styles) [] viewFun
override this.render() = ReactElementType.create !!viewWithStyles this.props []
let view (model: Model) (dispatch: Msg -> unit) : ReactElement =
let props = jsOptions<IProps>(fun p ->
p.model <- model
p.dispatch <- dispatch)
ofType<Component,_,_> props []
|
I think this code:
Should be:
So |
Yes sorry, I copied that part from your example but forgot to change it. |
I found a better way to do this. (related to #4) I though withStyles was causing performance problems in my App, so I dediced to implement my own HoC to do styling. The way I envisioned usage. let styles ( theme: Theme ) = {|
Button = style [
S.Margin "5vh 0 5vh 0"
]
|}
let render styled dispatch model =
let styled = inferType styles styled
div styled.Background [ .... omited ]
let view = render |> withStyles styles You need some adapters /// Declares a style class.
let style cssProps =
Some { Props = cssProps; ClassName = "" }
/// Runtime generated style class name.
let styleClass style : IHTMLProp list =
match style with
| Some s -> [ HTMLAttr.ClassName s.ClassName ]
| _ -> []
// mui Helper
let div style =
div <| styleClass style
Code follow: // Material UI makeStyles
let makeStyles'<'S, 'O, 'P> ( styles: 'S ) ( options: 'O )
: 'P -> IClassesProps =
!!((import "makeStyles" "@material-ui/core/styles") $ (styles, options))
// Material UI makeStyles
let makeStyles ( styles : StyleType ) ( options: StyleOption seq ) =
let opt = keyValueList CaseRules.LowerFirst options
let styles' =
match styles with
| StyleType.Styles styles -> (keyValueList CaseRules.LowerFirst styles |> unbox)
| StyleType.Func func -> func >> keyValueList CaseRules.LowerFirst
makeStyles'<_, _, unit> styles' opt
// Material UI useTheme
let useTheme<'T> () : 'T =
!!((import "useTheme" "@material-ui/core/styles") $ ())
/// Convert our CssStyle to IStyles list
let createSheet ( styleSheet: ITheme -> 'StyleSheet ) =
fun theme ->
let css = styleSheet theme
let idx k = ( k, css?(k) )
let conv ( k, v: CssStyle ) = Styles.Custom ( k, v.Props ) :> IStyles
JS.Object.keys css |> Seq.map ( idx >> conv ) |> List.ofSeq
/// Convert the IClassesProps to our CssStyle
let applySheet styleSheet ( classes: IClassesProps ) =
let css: 'StyleSheet = styleSheet ( useTheme<ITheme> () )
let convBack k v = Some { Props = v.Props; ClassName = k }
let styleIt k = css?(k) <- convBack classes?(k) css?(k)
JS.Object.keys css |> Seq.iter styleIt
css
let inline private uncurryView3 f key dispatch model =
f {| pkey = key; dispatch = dispatch; model = model |}
let inline private curryView3 f props =
let inline inferType ( fn : ( 's -> _ ) -> _ ) ( _ : 's ) = ()
inferType uncurryView3 props
f props.pkey props.dispatch props.model
/// Create a new styled component from a component and a style sheet.
let withStyles styleSheet ( fn: 'StyleSheet -> 'Dispatch -> 'Model -> ReactElement ) =
let name = ( box styleSheet ).GetHashCode().ToString()
let sheet = styleSheet |> createSheet |> StyleType.Func |> makeStyles
let useStyles = sheet [ StyleOption.Name name ]
let applyStyles f _ dispatch model =
f ( useStyles () |> applySheet styleSheet ) dispatch model
let fnC = fn |> applyStyles |> curryView3
let memoComp =
FunctionComponent.Of ( fnC, "styled",
fun x y -> equalsButFunctions ( x.model ) ( y.model ) )
// Defeat Fable currying optimization, so things can be cached.
fun ( key: string ) ->
uncurryView3 memoComp key
/// Useful helper for getting a copy of the anonymous record type to a parameter.
let inline inferType ( fn : _ -> 's ) ( s : 's ) = s
|
This thread is closed but is very important to figure out how the creation of HOCs work. Especially the part where you need to pass the model and the dispatch function through a props object. Maybe put this in the documentation as well? The current example just says:
The example in this thread is much more insightful.
Originally posted by @halcwb in #4 (comment)
The text was updated successfully, but these errors were encountered: