Shmew / Feliz.MaterialUI

Feliz-style Fable bindings for Material-UI
https://shmew.github.io/Feliz.MaterialUI/
MIT License
70 stars 19 forks source link

theme parameter always refers to the default theme in Styles.makeStyles #65

Closed inouiw closed 3 years ago

inouiw commented 3 years ago

I am expecting the theme parameter of Styles.makeStyles(fun styles theme -> to refer to the current theme but it is always the default theme.

Am I doing something wrong or is this an error in the library?

Extracts form my code:

let darkTheme = Styles.createMuiTheme([
  theme.palette.type'.dark
  theme.palette.background.paper "#1e1e1e"
])

type CssClasses = { RootDiv: string }

let useStyles = Styles.makeStyles(fun styles theme ->
  {
    RootDiv = styles.create [
      style.backgroundColor theme.palette.background.paper //"#1e1e1e"
    ]
  }
)

let app = 
  React.functionComponent(fun (model, dispatch) ->
    let classes = useStyles ()
    Mui.themeProvider [
      themeProvider.theme darkTheme
      themeProvider.children [
        Html.div [
          prop.className classes.RootDiv
          prop.children [
            Html.text "background should be #1e1e1e not white"
          ]
        ]
      ]
    ]
  )
cmeeren commented 3 years ago

I'm not using this actively, so I'm a bit out of the React hook stuff. I don't remember how that is supposed to work with relation to React.functionComponent and similar. My best suggestion is to ensure that you are using it correctly, and try plain JS to see if you can reproduce the problem there (if so, the problem isn't with Feliz.MaterialUI).

inouiw commented 3 years ago

Thank you for your reply.

If I split the app functional component in two functional components then the theme parameter is correct.

let RootDivComponent = React.functionComponent(fun (model, dispatch) ->
  let classes = useStyles ()
  Html.div [
    prop.className classes.RootDiv
    prop.children [
      Html.text "background is now #1e1e1e from darkTheme"
    ]
  ]
)

let app = React.functionComponent(fun (model, dispatch) ->
  Mui.themeProvider [
    themeProvider.theme darkTheme
    themeProvider.children [
      RootDivComponent(model, dispatch)
    ]
  ]
)

However my code used Fable 2. When I upgrade to Fable 3 then I get the warning "Feliz: using React.functionComponent in Fable 3 is obsolete". So now I want to update the components to use the [<ReactComponent>] attribute. However then I cannot use the useStyles hook any more. As I understand the material-ui documentation at https://material-ui.com/styles/api/#withstyles-styles-options-higher-order-component , they suggest to use withStyles. However I cannot find that function in this repository.

Is there an example how I can use styles in a component?

Update: It seems [<ReactComponent>] also creates a functional component. So I should be able to call let classes = useStyles (). However I currently get:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
cmeeren commented 3 years ago

Is there an example how I can use styles in a component?

I have no examples. Sounds weird that they suggest withStyles; I thought hooks basically replaced higher-order components. In any case, I'm afraid I can't be much help here. Since it works if you split it up, it seems this is not related to Feliz.MaterialUI, but rather to how hooks work with relation to React (and Feliz) components. Feel free to close if you agree, otherwise please clarify my misunderstanding.

inouiw commented 3 years ago

It works now. My last error ("Invalid hook call.") was because I defined the component as a variable RootDivComponent = ... instead of a method RootDivComponent () = .... So no error in this repository. You can close this issue.

Here the working solution

open Feliz
open Feliz.MaterialUI

let darkTheme = Styles.createMuiTheme([
  theme.palette.type'.dark
  theme.palette.background.paper "#1e1e1e"
])

type CssClasses = { RootDiv: string }

let useStyles = Styles.makeStyles(fun styles theme ->
  {
    RootDiv = styles.create [
      style.backgroundColor theme.palette.background.paper
    ]
  }
)

[<ReactComponent>]
let RootDivComponent () =
  let classes = useStyles ()
  Html.div [
    prop.className classes.RootDiv
    prop.children [
      Html.text "background is now #1e1e1e from darkTheme"
    ]
  ]

[<ReactComponent>]
let App =
  Mui.themeProvider [
    themeProvider.theme darkTheme
    themeProvider.children [
      RootDivComponent ()
    ]
  ]