Skip to content

Instantly share code, notes, and snippets.

@CodeMyUI
Created January 9, 2020 01:28
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 CodeMyUI/7ddfefd6cb99a72887790d9023a3b21f to your computer and use it in GitHub Desktop.
Save CodeMyUI/7ddfefd6cb99a72887790d9023a3b21f to your computer and use it in GitHub Desktop.
to-do react app
// If you like this app, feel free to hit
// the heart button :)
#app
// 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);
<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>
$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