57
Redux with JavaFX Michael Heinrichs & Manuel Mauky

Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Redux with JavaFXMichael Heinrichs & Manuel Mauky

Page 2: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Manuel MaukyMichael Heinrichs

Page 3: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Functional Reactive Programming

Page 4: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

● Declarative● Immutable data

● No side effects● Avoid state changes

Functional Programming

Page 5: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Active Communication

Button Controllercalls

Controllerlisten

Button Controllerfireevent

notify

Reactive Communication

Page 6: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Reactive Hell

Component Component

Component

Component

Component

Component

Component

Component

Page 7: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Reactive Streams

Publisher ProcessorEvent

ProcessorEvent

SubscriberEvent

PublisherEvent

Subscriber

Event

Page 8: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Functional Reactive Programming

Publisher ProcessorEvent

ProcessorEvent

SubscriberEvent

immutable

“dirty” “dirty”pure

Page 9: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Overview

Page 10: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Application

Action

StateVirtualSceneGraph

Frame-work

Action Creator

View Creator

Reducer

Event

Page 11: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Redux with Java

Page 12: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Demo

Page 13: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Actions

Page 14: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Application

Action

StateVirtualSceneGraph

Frame-work

Action Creator

View Creator

Reducer

Event

Page 15: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Action

Frame-work

Action CreatorEvent

MouseEventKeyEventActionEventChangeEvent

class SetFilterAction { Filter value;}

Page 16: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Demo

Page 17: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

State

Page 18: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Action

State

Frame-work

Action Creator

Reducer

Event

Page 19: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

state

newTodo filter

todos

todo1 todo2 ...

Page 20: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

class State { final String newTodo; final Filter filter; final Vector<Item> todos;}

class Item { final int id; final String text; final boolean completed;}

Page 21: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Demo

Page 22: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Reducer

Page 23: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Action

State

Reducer

State calcNewState(State currentState, Action action)

state_1 = calcNewState(state_0, action_0)

state_2 = calcNewState(state_1, action_1)

...

state_0

Initial state

Page 24: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

State calcNewState(State currentState, Action action)

state_0

state_1 = calcNewState(state_0, action_0)

state_2 = calcNewState(state_1, action_1)

...

Stream actions = Stream.of(action_0, ..., action_n)

State state_n = actions.reduce(state_0, calcNewState)

Page 25: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Demo

Page 26: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

State calcNewState(State state, Action action) {

if (action instanceof SetFilterAction) {

SetFilterAction filterAction = (SetFilterAction) action;

return state.withFilter(filterAction.getFilter());

}

...

return state;}

Page 27: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

state

newTodo filter

todos

todo1 todo2 ...

Page 28: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

State calcState(State state, Action action) { return State.build()

.withNewTodo( calcNewToDoState(state.newTodo, action) )

.withTodos( calcTodosState(state.todos, action) )

.withFilter( calcFilterState(state.filter, action) )

.create();}

Page 29: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction
Page 30: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction
Page 31: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Virtual SceneGraph

Page 32: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Action

StateVirtualSceneGraph

Frame-work

View Creator

Reducer

Page 33: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

class VNode {

private final Class<?> nodeClass;

private final Map<String, Array<VNode>> childrenMap; private final Map<String, VNode> singleChildMap;

private final Map<String, VProperty> properties;

private final Map<VEventType, VEventHandler> eventHandlers;

...}

Page 34: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

myVBox : VNode

nodeClass = VBox.classproperties = { spacing = 20}

myVBox : VNode

nodeClass = Label.classproperties = { prefWidth = 210, text = “You ...”}

myButton : VNode

nodeClass = Button.classproperties = { text = “Click Me”}eventHandlers = { … }

Page 35: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

public VNode view(State state) {

return VBox() .spacing(20) .children( Label() .text(String.format( "You clicked the button %d times", state.getCounter() )), Button() .text("Click Me!"), .onAction(e -> Actions.incCounter()); );}

Page 36: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Application

Action

StateVirtualSceneGraph

Frame-work

Action Creator

View Creator

Reducer

Event

Page 37: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Redux with FXML

Page 38: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Why FXML?Pros:

- well-known by JavaFX developers- SceneBuilder

Cons:

- Stateful → hard to integrate in a functional approach like redux

Page 39: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

FXML<VBox fx:controller="HelloController">

<children><Label fx:id="helloLabel"/><Button

text="Greet" onAction="#greetings"

/></children>

</VBox>

public class HelloController {

@FXMLprivate Label helloLabel;

public void greetings() {helloLabel.setText(

"Hello Sir or Madame");}

}

Page 40: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Let's see how others are doing it!→ Angular + Redux.JS

Page 41: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Idea- don't rerender whole UI on every update- keep UI stateful- connect to redux store and just update UI on changes

Page 42: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Angular

Page 43: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

@Component({selector: 'app-hello',template: '

<div><p>{{ helloLabel }}</p>

</div>'

})class HelloComponent {

public helloLabel: String

}

Angular Component (Controller)

Page 44: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

@Component({selector: 'app-hello',template: '

<div><p>{{ helloLabel }}</p>

</div>'

})class HelloComponent {

public helloLabel: Observable<String>

}

Change Type to "Observable" (Rx)

Page 45: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

@Component({selector: 'app-hello',template: '

<div><p>{{ helloLabel }}</p>

</div>'

})class HelloComponent {

@select(state => state.getGreeting())public helloLabel: Observable<String>

}

Framework magic:Connect observable to redux store

Page 46: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

@Component({selector: 'app-hello',template: '

<div><p>{{ helloLabel }}</p>

</div>'

})class HelloComponent {

@select(state => state.getGreeting())public helloLabel: Observable<String>

}

selector function:which value from the store should be used?

Page 47: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

@Component({selector: 'app-hello',template: '

<div><p>{{ helloLabel | async}}</p>

</div>'

})class HelloComponent {

@select(state => state.getGreeting())public helloLabel: Observable<String>

}

bind field to template

Page 48: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Adopt this for JavaFX

Page 49: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

public class HelloController {

@FXML private Label helloLabel;

}

Page 50: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

public class HelloController {@FXML private Label helloLabel;

@Injectprivate Selector<AppState> selector;

}

Selector is a framework utility

Page 51: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

public class HelloController {@FXML private Label helloLabel;

@Injectprivate Selector<AppState> selector;

public void initialize() {ObservableValue<String> value = selector.select(

state -> state.getGreeting());

}}

JavaFX ObservableValue

Page 52: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

public class HelloController {@FXML private Label helloLabel;

@Injectprivate Selector<AppState> selector;

public void initialize() {ObservableValue<String> value = selector.select(

state -> state.getGreeting());

helloLabel.textProperty().bind(value);}

}

Page 53: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Debugging / DevTool

Page 54: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Debugging with Redux- whole application state at one specific location → easy to find out "what's the

current state of the app"- each interaction within the app is explicit by using actions → actions can be

recorded to see what happened

Page 55: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

Redux-Javafx-DevtoolGithub: https://github.com/lestard/redux-javafx-devtool

- current state of the application- all actions- time-travel through action history

Page 56: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

User interaction → Are the correct actions created?

ActionCreator / UI component

Is the state correct?

Does the selector yields correct values?

Bug

no

yes

reducerno

yes

selectorno

rendering of the UI component

yes

error source

Page 57: Redux with JavaFX - RainFocus...Debugging with Redux - whole application state at one specific location → easy to find out "what's the current state of the app" - each interaction

ReduxFX:

Redux JavaFX DevTool:

https://github.com/netopyr/reduxfx

https://github.com/lestard/redux-javafx-devtool