title: | Flux Reflux React |
---|---|
data-transition-duration: | 1000 |
css: | css/presentation.css |
Mike Groseclose (@mikrofusion)
- Part I: Some Theory
- Part II: React
- Part III: Flux / Reflux / Redux
- Part V: A Bit Of Code
data-rotate: | 100 |
---|---|
data-rotate-y: | 100 |
data-rotate: | 0 |
---|---|
data-rotate-y: | 0 |
- Don’t always return the same result given the same input.
- Can cause side effects.
var count = 0;
function increment() {
return ++count;
}
function debug(str) {
console.log(str);
}
Expressions made from impure functions are hard to predict.
Expressions made from impure functions are hard to test.
- Lack of testing and predictability makes applications:
- harder to reason about.
- harder to scale.
- harder to refactor with confidence.
Expressions made from impure functions create fragile applications.
- Will always evaluate to the same result given the same input.
- Stateless.
- No side effects.
- Expressions that are constructed from pure functions.
- Pure functions are referentially transparent.
- An expression which is referentially transparent can be replaced with its value and have no impact on the system.
Referencially transparent functions are like black boxes.
- With black boxes implementation details do not matter.
- When working with a black box the only concern is inputs and outputs.
- One black box can be replaced with another black box as long as same data in results in same data out.
- Simplifies the code making it easier to reason about.
- Makes testing easier (focus on inputs and outputs)
- Allows for more confident refactors.
- Less fragile, more scalable code.
function multiply(x, y) {
result = 0;
for(var i = 0; i < y; i++) {
result += x;
}
return result;
}
function multiply(x, y) {
return x * y;
}
Rather than storing the current state, store the initial state and the events that lead to the current state.
input: 0
event: +3
event: -1
output: 2
data-rotate: | 100 |
---|---|
data-rotate-y: | 100 |
A JavaScript library for building user interfaces.
data-rotate: | 0 |
---|---|
data-rotate-y: | 0 |
React is only a view component.
React is technology stack agnostic.
- React focuses on being simple and declarative
- React is about building reusable components.
- Similar to black boxes, React components are extremely encapsulated making code reuse, testing, and separation of concerns easy.
In order to be stay encapsulated React uses some unfamiliar conventions.
React combines markup and view logic into a single component.
This creates components which are easier to extend and maintain.
React recommends using JSX to give the markup a familiar syntax.
var Bar = require('./foo');
var Foo = React.createClass({
function() {
return (
<div>
<Bar name={this.props.name} />
</div>
);
}
});
data-y: | r3000 |
---|---|
data-rotate: | 100 |
data-rotate-y: | 100 |
data-y: | r0 |
---|---|
data-rotate: | 0 |
data-rotate-y: | 0 |
Flux is the application architecture that Facebook uses to build client-side web apps.
Flux complements React's composable view components by utilizing a unidirectional data flow.
Flux takes a more functional approach to how data is handled in a web application.
Flux is a pattern, not a framework.
- RefluxJS and Redux are framework implementations of the Flux architecture.
- RefluxJS strive to be more Functional Reactive Programming (FRP) friendly and simplify Flux.
- Redux is completely decoupled from React and has live code editing combined with a time traveling debugger.
data-z: | r1500
|
---|
data-z: | r0 |
---|
The dispatcher really contains no business logic and is mostly the same between applications using Flux.
It can be argued that the dispatcher is mostly an implementation detail.
RefluxJS removes the dispatcher from the flow, by pushing its responsibility into the actions.
Redux uses a single store to store the state of the application.
Redux uses the Event Sourcing Pattern and adds Reducers to mutate the store.
Pure functions that specify how the application’s state changes in response to an action.
(previousState, action) => newState
data-rotate: | 100 |
---|---|
data-rotate-y: | 100 |
data-rotate: | 0 |
---|---|
data-rotate-y: | 0 |
Code snippets taken from: https://github.com/spoike/refluxjs-todo
TodoActions = Reflux.createActions([
"toggleItem",
"toggleAllItems",
"addItem",
"removeItem",
"clearCompleted",
"editItem"
]);
Reflux.createStore({
listenables: [TodoActions], // set up listeners
onEditItem: function(itemKey, newLabel) {
...
},
...
updateList: function(list){
// sends the updated list to all listening components
this.trigger(list);
},
...
});
var TodoApp = React.createClass({
// sets state.list when store does trigger(updatedlist)
mixins: [Reflux.connect(todoListStore,"list")],
render: function() {
return (
<div>
<TodoHeader />
<ReactRouter.RouteHandler list={this.state.list} />
<TodoFooter list={this.state.list} />
</div>
);
}
});
Code snippets taken from: https://github.com/rackt/redux/tree/master/examples/todomvc
export function addTodo(text) {
return { type: types.ADD_TODO, text };
}
export function deleteTodo(id) {
return { type: types.DELETE_TODO, id };
}
...
export default function todos(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return [{
id: state.length,
completed: false,
text: action.text
}, ...state];
case DELETE_TODO:
return state.filter(todo =>
todo.id !== action.id
);
...
class TodoItem extends Component {
constructor(props, context) {
...
this.state = { editing: false };
}
...
render() {
const {todo, completeTodo, deleteTodo} = this.props;
...
return (
<li className={classnames({
completed: todo.completed,
editing: this.state.editing
})}>
{element}
</li>
);
}
data-rotate: | 100 |
---|---|
data-rotate-y: | 100 |