Skip to content

Instantly share code, notes, and snippets.

@leolana
Last active August 21, 2018 09:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leolana/fd86cd07a53517d74ae5abde5db1e4f0 to your computer and use it in GitHub Desktop.
Save leolana/fd86cd07a53517d74ae5abde5db1e4f0 to your computer and use it in GitHub Desktop.
demo-todolist-redux
import * as types from "./../constants/ActionTypes";
export const addItem = (todoItem, index) => {
const item = {
index,
value: todoItem.newItemValue,
done: false
};
return {
type: types.ADD_ITEM,
item
};
};
export const removeItem = itemIndex => {
return {
type: types.REMOVE_ITEM,
itemIndex
};
};
export const markTodoDone = itemIndex => {
return {
type: types.MARK_TODO_DONE,
itemIndex
};
};
export const ADD_ITEM = 'ADD_ITEM';
export const REMOVE_ITEM = 'REMOVE_ITEM';
export const MARK_TODO_DONE = 'MARK_TODO_DONE';
import React, { Component } from "react";
import TodoHeader from "../../components/TodoHeader/TodoHeader";
import TodoList from "../../components/TodoList/TodoList";
import TodoForm from "../../components/TodoForm/TodoForm";
import logo from "./logo.svg";
import "./App.css";
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<div id="main">
<TodoHeader />
<TodoList />
<TodoForm />
</div>
</div>
);
}
}
export default App;
import React, { Component } from "react";
import { connect } from "react-redux";
import { addItem } from './../../actions/todoItem';
import "./TodoForm.css";
class TodoForm extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
this.refs.itemName.focus();
}
onSubmit(event) {
event.preventDefault();
const { dispatch, todoItems } = this.props;
var newItemValue = this.refs.itemName.value;
if(newItemValue) {
dispatch(addItem({newItemValue}, todoItems.length + 1));
this.refs.form.reset();
}
}
render () {
return (
<form ref="form" onSubmit={this.onSubmit} className="form-inline">
<input type="text" ref="itemName" className="form-control" placeholder="add a new todo..."/>
<button type="submit" className="btn btn-default">Add</button>
</form>
);
}
}
const mapStateToProps = state => {
const { todoItems } = state;
return {
todoItems
};
};
export default connect(mapStateToProps)(TodoForm);
import React, { Component } from "react";
import { connect } from "react-redux";
import TodoListItem from "../TodoListItem/TodoListItem";
import "./TodoList.css";
class TodoList extends Component {
render() {
const { todoItems } = this.props;
const todoListItems =
todoItems &&
todoItems.map((item, index) => (
<TodoListItem
key={index}
item={item}
index={index}
/>
));
return <ul className="list-group"> {todoListItems} </ul>;
}
}
const mapStateToProps = state => {
const { todoItems } = state;
return {
todoItems
};
};
export default connect(mapStateToProps)(TodoList);
import React, { Component } from "react";
import { connect } from "react-redux";
import { markTodoDone, removeItem } from './../../actions/todoItem';
import "./TodoListItem.css";
class TodoListItem extends Component {
constructor(props) {
super(props);
this.onClickClose = this.onClickClose.bind(this);
this.onClickDone = this.onClickDone.bind(this);
}
onClickClose() {
const { dispatch } = this.props;
var index = parseInt(this.props.index, 10);
dispatch(removeItem(index));
}
onClickDone() {
const { dispatch } = this.props;
var index = parseInt(this.props.index, 10);
dispatch(markTodoDone(index));
}
render() {
var todoClass = this.props.item.done ? "done" : "undone";
return (
<li className="list-group-item ">
<div className={todoClass}>
<span
className="ll-icon ll-icon-ok icon"
aria-hidden="true"
onClick={this.onClickDone}
/>
{this.props.item.value}
<button type="button" className="close" onClick={this.onClickClose}>
&times;
</button>
</div>
</li>
);
}
}
const mapStateToProps = state => {
const { todoItems } = state;
return {
todoItems
};
};
export default connect(mapStateToProps)(TodoListItem);
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import './index.css';
import App from './containers/App/App';
import rootReducer from './reducers/index';
import registerServiceWorker from './registerServiceWorker';
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
applyMiddleware(thunkMiddleware)
);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
registerServiceWorker();
import { combineReducers } from "redux";
import todoItems from "./todoItems";
const rootReducer = combineReducers({
todoItems
});
export default rootReducer;
import * as types from "./../constants/ActionTypes";
const initialState = [
{ index: 1, value: "Aprender react", done: false },
{ index: 2, value: "Ir a farmácia", done: true },
{ index: 3, value: "Comprar comida para o cachorro", done: true }
];
export default (state = initialState, action) => {
switch (action.type) {
case types.ADD_ITEM:
return [...state, action.item];
case types.REMOVE_ITEM:
state.splice(action.itemIndex, 1);
return [...state];
case types.MARK_TODO_DONE:
let todo = state[action.itemIndex];
state.splice(action.itemIndex, 1);
todo.done = !todo.done;
todo.done ? state.push(todo) : state.unshift(todo);
return [...state];
default:
return state;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment