to-do app made by using react.
Created
January 9, 2020 01:28
-
-
Save CodeMyUI/7ddfefd6cb99a72887790d9023a3b21f to your computer and use it in GitHub Desktop.
to-do react app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// If you like this app, feel free to hit | |
// the heart button :) | |
#app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Component Structure | |
// -------------------- | |
// Container | |
// --> Title | |
// --> Form | |
// --> List | |
// ----> Todo | |
// --> Footer | |
// stateless component | |
const Title = () => { | |
return ( | |
<div id="titleWrapper"> | |
<h2 className="textCenter">To-do List</h2> | |
</div> | |
); | |
}; | |
class Form extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
value: '' | |
}; | |
this.handleChange = this.handleChange.bind(this); | |
this.handleNewTodoAddition = this.handleNewTodoAddition.bind(this); | |
} | |
handleChange(event) { | |
this.setState({ | |
value: event.target.value | |
}); | |
} | |
handleNewTodoAddition() { | |
if(this.input.value !== '') { | |
this.props.addTodo(this.input.value); | |
this.setState({ | |
value: '' | |
}); | |
this.input.placeholder = "Add todo here..."; | |
} | |
} | |
render() { | |
return ( | |
// ref should be passed a callback | |
// with underlying dom element as its | |
// argument to get its reference | |
<div id="form"> | |
<input | |
ref={node => { | |
this.input = node; | |
}} | |
value={this.state.value} | |
placeholder="Add todos here..." | |
autocomplete="off" | |
onChange={this.handleChange} | |
/> | |
<button | |
onClick={this.handleNewTodoAddition} | |
> | |
+ | |
</button> | |
</div> | |
); | |
} | |
} | |
const Todo = ({todo, remove}) => { | |
// single todo | |
return ( | |
<p className="todos"> | |
{todo.value} | |
<span | |
className="removeBtn" | |
onClick={()=> { | |
remove(todo.id) | |
}}> | |
x | |
</span> | |
</p> | |
); | |
}; | |
const List = ({todos, remove}) => { | |
let allTodos = []; | |
if(todos.length > 0) { | |
allTodos = todos.map(todo => { | |
// passing todo and remove method reference | |
return (<Todo todo={todo} remove={remove} />); | |
//return (<p>{todo.value}</p>); | |
}); | |
} else { | |
allTodos.push(<h3 id="acu">All caught up !</h3>); | |
} | |
return ( | |
<div id="list"> | |
<p id="info"> Your Todos: </p> | |
{allTodos} | |
</div> | |
); | |
}; | |
const Footer = () => { | |
return ( | |
<div id="footer"> | |
<a href="http://iamarshad.com" target="_blank"> | |
<p> | |
Arshad Khan | |
</p> | |
</a> | |
</div> | |
); | |
}; | |
class Container extends React.Component { | |
constructor(props) { | |
super(props); | |
// data for introduction to app | |
// for new users | |
const introData = [ | |
{ | |
id: -3, | |
value: "Hi! This is a simple todo list app made by REACT <3" | |
}, | |
{ | |
id: -2, | |
value: "Hover over todos and click on `X` to delete them!" | |
}, | |
{ | |
id: -1, | |
value: "Add new todos and come back any time later, I will save them for you!" | |
} | |
]; | |
const localData = localStorage.todos && JSON.parse(localStorage.todos); | |
this.state = { | |
data: localData || introData | |
}; | |
// binding methods | |
this.addTodo = this.addTodo.bind(this); | |
this.removeTodo = this.removeTodo.bind(this); | |
} | |
// Handler to update localStorage | |
updateLocalStorage() { | |
if (typeof(Storage) !== "undefined") | |
localStorage.todos = JSON.stringify(this.state.data); | |
} | |
// Handler to add todo | |
addTodo(val) { | |
let id; | |
// if localStorage is available then increase localStorage count | |
// else use global window object's id variable | |
if (typeof(Storage) !== "undefined") { | |
id = Number(localStorage.count); | |
localStorage.count = Number(localStorage.count) + 1; | |
} else { | |
id = window.id++; | |
} | |
const todo = { | |
value: val, | |
id: id | |
}; | |
this.state.data.push(todo); | |
// update state | |
this.setState({ | |
data: this.state.data | |
}, () => { | |
// update localStorage | |
this.updateLocalStorage(); | |
}); | |
} | |
// Handler to remove todo | |
removeTodo(id) { | |
// filter out the todo that has to be removed | |
const list = this.state.data.filter(todo => { | |
if (todo.id !== id) | |
return todo; | |
}); | |
// update state | |
this.setState({ | |
data: list | |
}, () => { | |
// update localStorage | |
this.updateLocalStorage(); | |
}); | |
} | |
componentDidMount() { | |
localStorage.clear(); | |
if (typeof(Storage) !== "undefined") { | |
if(!localStorage.todos) { | |
localStorage.todos = JSON.stringify(this.state.data); | |
} | |
if(!localStorage.count) { | |
localStorage.count = 0; | |
} | |
} else { | |
console.log("%cApp will not remember todos created as LocalStorage Is Not Available", | |
"color: hotpink; background: #333; font-size: x-large;font-family: Courier;"); | |
window.id = 0; | |
} | |
} | |
render() { | |
return ( | |
<div id="container"> | |
<Title /> | |
<Form addTodo={this.addTodo} /> | |
<List todos={this.state.data} remove={this.removeTodo} /> | |
<Footer /> | |
</div> | |
); | |
} | |
} | |
ReactDOM.render(<Container />, app); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$black: #333 | |
$purple: #6d639a | |
$pink: #d63f74 | |
$white: #fefefe | |
$grey: rgba($black, .5) | |
* | |
font-family: Bungee Hairline !important | |
font-weight: bold | |
color: $black | |
border-color: $black | |
line-height: 1.5 | |
\::-webkit-input-placeholder | |
color: rgba($pink, .5) | |
\:-moz-placeholder | |
color: rgba($pink, .5) | |
\::-moz-placeholder | |
color: rgba($pink, .5) | |
\:-ms-input-placeholder | |
color: rgba($pink, .5) | |
body | |
background: #fefefe | |
.textCenter | |
text-align: center | |
.removeBtn | |
position: absolute | |
right: 8px | |
top: 50% | |
transform: translateY(-50%) | |
#container | |
margin: auto | |
text-align: center | |
max-width: 700px | |
margin: 60px auto 0 auto | |
padding: 0px 20px | |
h2 | |
margin-bottom: 30px | |
color: $black | |
#form | |
margin-bottom: 50px | |
#info | |
padding: 7px | |
text-align: left | |
color: $grey | |
input | |
background: transparent | |
border: solid 1px | |
padding: 7px 10px | |
border-right: none | |
width: 70% | |
color: $black | |
border-color: $pink | |
&:focus, &:active | |
outline: none | |
button | |
border: solid 1px $pink | |
padding: 7px 10px | |
background: rgba($pink, .8) | |
cursor: pointer | |
width: 15% | |
min-width: 20px | |
transition: all 100ms linear 80ms | |
color: $white | |
line-height: 1 | |
font-size: 18px | |
&:focus, &:active | |
outline: none | |
&:hover, &:active | |
background: rgba($pink, 1) | |
button, input | |
vertical-align: middle | |
height: 35px | |
box-sizing: border-box | |
#acu | |
text-align: left | |
padding: 7px | |
#footer | |
margin: 50px 0 30px 0 | |
padding-top: 30px | |
text-align: left | |
border-top: dotted 2px $pink | |
p | |
padding: 7px | |
display: inline-block | |
color: $black | |
transition: all 100ms linear 80ms | |
&:hover | |
color: $pink | |
&:before, &:after | |
color: $purple | |
&:before | |
content: '<' | |
&:after | |
content: '/>' | |
.todos | |
transition: all 100ms linear 100ms | |
position: relative | |
text-align: left | |
margin: 30px auto | |
padding: 7px | |
padding-right: 28px | |
border: solid 1px transparent | |
color: $purple | |
&:hover | |
cursor: pointer | |
border: solid 1px | |
span | |
visibility: visible | |
color: inherit | |
span | |
transition: all 100ms linear 100ms | |
visibility: hidden | |
&:hover | |
cursor: pointer | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment