var alt = require('alt');
class LocationActions {
updateLocations(locations) {
return locations;
}
fetchLocations() {
return (dispatch) => {
// we dispatch an event here so we can have "loading" state.
dispatch();
LocationSource.fetch()
.then((locations) => {
// we can access other actions within our action through `this.actions`
this.updateLocations(locations);
})
.catch((errorMessage) => {
this.locationsFailed(errorMessage);
});
}
}
locationsFailed(errorMessage) {
return errorMessage;
}
}
module.exports = alt.createActions(LocationActions);
LocationActions.js
var alt = require('/alt');
var LocationActions = require('../actions/LocationActions');
class LocationStore {
constructor() {
this.locations = [];
this.bindListeners({
handleUpdateLocations: LocationActions.UPDATE_LOCATIONS
});
}
handleUpdateLocations(locations) {
this.locations = locations;
}
}
module.exports = alt.createStore(LocationStore, 'LocationStore');
LocationStore.js
var React = require('react');
var LocationStore = require('../stores/LocationStore');
var Locations = React.createClass({
getInitialState() {
return LocationStore.getState();
},
componentDidMount() {
LocationStore.listen(this.onChange);
},
componentWillUnmount() {
LocationStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
render() {
return (
<ul>
{this.state.locations.map((location) => {
return (
<li>{location.name}</li>
);
})}
</ul>
);
}
});
module.exports = Locations;
export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
// action creators - functions that create actions
// actions are JS objects in the form of {type: ACTION, data}
export function addTodo(text) {
return { type: ADD_TODO, text }
}
export function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
export function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter }
}
import { combineReducers } from 'redux'
import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters } from './actions'
const { SHOW_ALL } = VisibilityFilters
function visibilityFilter(state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
function todos(state = [], action) {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
text: action.text,
completed: false
}
]
case TOGGLE_TODO:
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
default:
return state
}
}
const todoApp = combineReducers({
visibilityFilter,
todos
})
export default todoApp
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
import { addTodo,
toggleTodo,
setVisibilityFilter,
VisibilityFilters } from './actions'
// Log the initial state
console.log(store.getState())
// Every time the state changes, log it
let unsubscribe = store.subscribe(() =>
console.log(store.getState())
)
// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))
store.dispatch(addTodo('Learn about reducers'))
store.dispatch(addTodo('Learn about store'))
store.dispatch(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))
// Stop listening to state updates
unsubscribe()
import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
}
}
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
l
import React, { PropTypes } from 'react'
import Todo from './Todo'
const TodoList = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
TodoList.propTypes = {
todos: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
completed: PropTypes.bool.isRequired,
text: PropTypes.string.isRequired
}).isRequired).isRequired,
onTodoClick: PropTypes.func.isRequired
}
export default TodoList
import React, { PropTypes } from 'react'
const Todo = ({ onClick, completed, text }) => (
<li
onClick={onClick}
style={{
textDecoration: completed ? 'line-through' : 'none'
}}
>
{text}
</li>
)
Todo.propTypes = {
onClick: PropTypes.func.isRequired,
completed: PropTypes.bool.isRequired,
text: PropTypes.string.isRequired
}
export default Todo