Hi guys! Revery is awesome. I try to create a todo list to try out revery, but there is an issue when I want to delete one list or all todos.
gist
or the code
open Revery.UI;
open Revery.UI.Components;
open Revery.Core;
open Revery.Core.Window;
open Revery.Core.Events;
open Revery.Core.Key;
type todo = {
id: int,
description: string,
};
type state = {
currentInput: string,
todos: list(todo),
};
type action =
| UpdateInput(string)
| AddTodo(todo)
| RemoveTodo(int)
| Backspace
| CleanAll;
let reducer = (state, action) => {
switch (action) {
| UpdateInput(currentChar) => {
...state,
currentInput: state.currentInput ++ currentChar,
}
| AddTodo(todo) => {currentInput: "", todos: [todo, ...state.todos]}
| RemoveTodo(id) =>
let currentTodo = List.filter(todo => todo.id !== id, state.todos);
{currentInput: "", todos: currentTodo};
| Backspace =>
let length = String.length(state.currentInput);
if (length > 0) {
{
...state,
currentInput: String.sub(state.currentInput, 0, length - 1),
};
} else {
state;
};
| CleanAll => {currentInput: "", todos: []}
};
};
let textStyle =
Style.make(
~fontSize=20,
~fontFamily="Roboto-Regular.ttf",
~color=Colors.black,
(),
);
module TodoList = (
val component((render, ~window, ~children, ()) =>
render(
() => {
let ({currentInput, todos}, dispatch) =
useReducer(reducer, {currentInput: "", todos: []});
let response = keyEvent => {
switch (keyEvent.key) {
| KEY_ENTER =>
dispatch(
AddTodo({
id: List.length(todos),
description: currentInput,
}),
)
| KEY_BACKSPACE => dispatch(Backspace)
| _ => ()
};
};
useEffect(() => {
let unsubscribe = Event.subscribe(window.onKeyDown, response);
unsubscribe;
});
useEffect(() => {
let unsubscribe =
Event.subscribe(window.onKeyPress, keyPress =>
dispatch(UpdateInput(keyPress.character))
);
unsubscribe;
});
let items =
List.map(
todo =>
<Clickable onClick={_ => dispatch(RemoveTodo(todo.id))}>
<view
style={Style.make(
~height=30,
~marginTop=5,
~marginBottom=5,
~marginLeft=20,
(),
)}>
<text style=textStyle> {todo.description} </text>
</view>
</Clickable>,
todos,
);
<view style={Style.make(~flexGrow=1, ())}>
<view
style={Style.make(
~height=50,
~backgroundColor=Colors.green,
~justifyContent=LayoutTypes.JustifyCenter,
~alignItems=LayoutTypes.AlignCenter,
(),
)}>
<text style=textStyle> {currentInput ++ "|"} </text>
</view>
<view
style={Style.make(
~flexGrow=1,
~backgroundColor=Colors.hotPink,
(),
)}>
...items
</view>
<Button title="Clean All" onClick={_ => dispatch(CleanAll)} />
</view>;
},
~children,
)
)
);
let init = app => {
let window = App.createWindow(app, "TodoList");
let render = () => {
<TodoList window />;
};
Revery.UI.start(window, render);
};
App.start(init);
the dispatch seems to be called, and the state is updated but the screen still shows the deleted list.
I think this is related to #170. Will look into this later today
This is awesome @broerjuang ! Thank you for putting that together. Would 鉂わ笍 to include this as an example once we get this issue fixed (it's nice to see apps working end-to-end).
I troubleshooted this a bit - indeed, I see the state being updated.
I also added this line to force re-rendering every frame:
Revery.UI.start(window, render);
+ Window.setShouldRenderCallback(window, () => true);
And the bug still reproduced. I suspect this is actually a bug with our native reconciler reason-reactify - it's possible its another manifestation of https://github.com/revery-ui/reason-reactify/pull/44 , or a new bug, possibly in the reconcileChildren method here: https://github.com/revery-ui/reason-reactify/blob/1f4801a8acda4da549239dad2cd958467bccff5c/lib/Reactify.re#L506
It's also possible that the reconciler is working fine, but for some reason we're not applying the updates correctly - like maybe the parent#removeChild isn't working as we expect here:
https://github.com/revery-ui/revery/blob/e95d0f1ad6761cbce0fd8290e085f00ac59cbdf3/src/UI/UiReconciler.re#L59
We could add some logging to that removeChild function, see if it's being called in the clear case, and validate that the parent child count actually decreases after the call to parent#removeChild.
Another helpful next step would be to see if we could prune this down to a minimal repro, and then add it as a test case in the reason-reactify repo.
Thanks again for trying it out - look forward to including this as an example once we work out this bug!
Can this be closed?
The reconciler has changed a lot since this (we use brisk-renconciler now instead of reason-reactify), so it's likely it has changed or is a different manifestation.
I'll close this, but feel free to open a new issue with an updated repro if there is still a problem here.