-
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
Feliz.Router.BasePath stopped navigation #24
Comments
I guess it's difficult/not possible to provide some code to reproduce. This is strange, the only use of Fable.Promise I can see in all the dependencies of Feliz.Router.BasePath is this call to Promise.start in Feliz.UseElmish. It's true we've have changed the code emitted for |
It would be good to know if other projects using |
@alfonsogarciacaro, I know my description was not helpful for further investigation. I was already happy to determine Promise as the cause since no error or warning came up during compilation. |
"UseElmish" counter works fine with Fable.Promise 3.1 |
...and Feliz.Router has no dependency on Fable.Promise. |
I'm getting the same issue and I think I've narrowed it down to Feliz.UseElmish when the update function returns a state AND another Cmd that isn't Cmd.none. It seems that the returned Cmd isn't processed until something else triggers the update. I'll keep digging to pin it down. |
Thanks for that @TWith2Sugars! Would you happen to have some code you can share? I could try to compile and see if there's something out of place in the generated JS. |
I do but it's part of a rather large private project, let me try and distill it to something smaller. |
Right, I've managed to create a repo from the Feliz template and isolate the issue: https://github.com/TWith2Sugars/FelizPromiseIssue I've taken the counter example and add an extra Msg IncrementAgain The update function will increment the state and return a Cmd.ofMsg Increment When you hit IncrementAgain you'll see the state only increases by 1. |
Let me know if there is anything else I can do to help. |
Thanks a lot for this @TWith2Sugars! This is super helpful. By testing your repo I realized the reason of the different behaviour was the change in the ...However, I'm unsure if going back is the right thing to do for Fable.Promise. Actually after investigating I concluded I was actually using an implementation of Delay/Run that may not be a good fit for JS promises. See #25 TBH, even after spotting the code that's causing the wrong behaviour I still don't know what's actually happening. It's difficult to follow the program flow in UseElmish because it uses multiple React hooks. My intuition is that UseElmish somehow "relied" on a quirk of the previous Fable.Promise implementation. For example, if I replace promise with async here, the problem is still happening: let rec dispatch (msg: 'Msg) =
async {
let mutable nextMsg = Some msg
while nextMsg.IsSome && not (token.current.IsCancellationRequested) do
let msg = nextMsg.Value
let (state', cmd') = update msg state.current
cmd' |> List.iter (fun sub -> sub dispatch)
nextMsg <- ring.current.Pop()
state.current <- state'
setChildState()
}
|> Async.StartImmediate It'd be ideal if the issue could be solved on the static member useElmish<'State,'Msg> (init: 'State * Cmd<'Msg>, update: 'Msg -> 'State -> 'State * Cmd<'Msg>, dependencies: obj[]) =
let exec dispatch cmd =
cmd |> List.iter (fun call -> call dispatch)
let setStateRef = React.useRef(ignore)
let initState, initCmd, dispatch = React.useMemo(fun () ->
let initState, initCmd = init
let rb = RingBuffer(10)
let mutable reentered = false
let mutable state = initState
let rec dispatch msg =
if reentered then
rb.Push msg
else
reentered <- true
let mutable nextMsg = Some msg
while Option.isSome nextMsg do
let msg = nextMsg.Value
let (model', cmd') = update msg state
setStateRef.current model'
cmd' |> exec dispatch
state <- model'
nextMsg <- rb.Pop()
reentered <- false
initState, initCmd, dispatch
)
let state, setState = React.useState(initState)
setStateRef.current <- setState
React.useEffect((fun () ->
initCmd |> exec dispatch
React.createDisposable(fun () ->
getDisposable state
|> Option.iter (fun o -> o.Dispose())
)
), [||])
(state, dispatch) |
Hello @alfonsogarciacaro, I am currently working for a client who is using My reason is that by not using Also the Elmish Wouldn't it make sense to try using Elmish |
I've tested those replacements in my larger app and it's resolved all of my issues 👍 |
@alfonsogarciacaro, this would also fix the initial issue, routing would work again. @MangelMaxime, I used to work with Elmish |
I think what @MangelMaxime is saying is we can use Following Feliz.UseElmish, I also implemented the hook for Fable.Lit. Then I tried to make it compatible with Elmish Program to take advantage of Elmish add-ons as @MangelMaxime says. But after reading his last comment I tried to use the Elmish program directly and it seems it can be made to work by using an observable-like middle agent: https://github.com/fable-compiler/Fable.Lit/pull/21/files We can try to do the same for Feliz.UseElmish. The API can be kept the same by building internally the program with the @TWith2Sugars @SCullman Are you using the alternative |
@alfonsogarciacaro Did understand what I was saying. I am not saying we should remove The idea being that if you want to augment your Elmish loops with the current |
Not in production just as a quick check to see if worked. I've just pinned the Fable.Promise dependency to 2.2.2 for the time being. |
After a dotnet paket update I noticed that navigation with Feliz.Router.BasePath stopped working, or better, the hook stopped setting a new state with the current page.
I was able to track it down to Fable.Promise 3.1. When I downgraded to 2.2.2, it worked again.
I still have no idea what is happening, and whether Feliz.Router or the React.useElmish hook is also affected.
The text was updated successfully, but these errors were encountered: