Like A Girl

Pushing the conversation on gender equality.

Code Like A Girl

Think ‘React’ively

Make a simple app-Part II

The basic prototype of how a Todo app is done. Let’s add a few features to it.

We will add two functionalities to our app- Update and Delete.

Since, React allows us to develop components independently. Let’ s make a separate component for each of the memo that we save called Post.

In this case, we will have multi-level hierarchy.

class Display extends React.Component{
constructor(props){
super(props);
this.state={
todos:[]
}
}
componentWillReceiveProps(nextProps){
this.setState({
todos:nextProps.display
})
}
render(){
var renderList=this.state.todos;
var listElements=[];
for(var i=0;i<renderList.length;i++){
listElements.push(<Post text={renderList[i]} i={i}/>);
}
return(
<div>{listElements}</div>
)
}
}
class Post extends React.Component{
constructor(props){
super(props);
this.state={
text:this.props.text
}
}
render(){
return(
<div>{this.props.text}</div>
)
}

}

The above code functions are the same as the previous one.

The question is, what is the reason behind doing this? As, we are going to add two more functionalities in our Todo App, the code will become too complex if we add everything in the same component. Hence, make a separate component and add those functionalities to it.

We will first give the Delete function a try. Add a function deleteTodo() to the Todo component and bind it to ‘this’ in the constructor and pass it through the hierarchy to the Post component.

Note that: For deleteTodo(), we will require a parameter i for deleting the specific Todo that we want. For achieving that, we will pass the value of i, from the parent component of Post,i.e., the Display component.

After doing all the necessary changes, our components will look like this-

class Todo extends React.Component{
constructor(props){

this.deleteTodo=this.deleteTodo.bind(this);
}
}
deleteTodo(i){
var list=this.state.list;
list.splice(i,1);
this.setState({
list:list
})
}
render(){
return(
<div>
<Save text={this.state.input} saveText={this.addTodo}/>
<Display display={this.state.list} deleteTodo={this.deleteTodo}/>
</div>
)
}
}
class Display extends React.Component{

render(){
var renderList=this.state.todos;
var listElements=[];
for(var i=0;i<renderList.length;i++){
listElements.push(<Post text={renderList[i]} i={i} deleteTodo={this.props.deleteTodo}/>);
}
return(
<div>{listElements}</div>
)
}
}
class Post extends React.Component{
constructor(props){
super(props);
this.state={
text:this.props.text
}
this.deletethisTodo=this.deletethisTodo.bind(this);
}
deletethisTodo(i){
this.props.deleteTodo(i);
}
render(){
return(
<div><span>{this.props.text} </span><button onClick={this.deletethisTodo.bind(this,this.props.i)}>Delete</button></div>
)
}

}

The onClick() of Post Component is binding the function deletethisTodo() with the deleteTodo() and the i value getting passed. To know about how to pass arguments through a function in React, please go to the link here.

And the splice() used in Todo is a Javascript function used for mutating arrays.

Let’s move to the Update function now. If you click on a particular Todo, you should be able to modify it using update.We will make an edit button, that button will render an input box and an update button when clicked.

class Post extends React.Component{
constructor(props){
super(props);
this.state={
text:this.props.text,
isEdit:false
}
this.deletethisTodo=this.deletethisTodo.bind(this);
this.editTodo=this.editTodo.bind(this);
}
editTodo(){
this.setState({
isEdit:true
})
}
render(){
if(this.state.isEdit===false){
return(
<div><span>{this.props.text} </span><button onClick={this.deletethisTodo.bind(this,this.props.i)}>Delete</button><button onClick={this.editTodo}>edit</button></div>
)
}else{
return(
<div><input type=’text’/>
<button>Update</button>
</div>
)
}
}
}

Here, isEdit is a boolean variable which is being used for checking whether the edit button was clicked or not. Since, we require our input box to be filled with the same value,so, pass value={this.state.text} in your <input> of else loop.

All that is left is to capture the change in input box and update the list array.

We will define a onChange() in the input box of else part.

class Post extends React.Component{
constructor(props){

this.onchange=this.onchange.bind(this);
}
onchange(e){
this.setState({
text:e.target.value
})
}
render(){

}else{
return(
<div><input type=’text’ value={this.state.text} onChange={this.onchange}/>
<button>Update</button>
</div>
)
}
}
}

This onChange() will capture all the changes done to text in input box.We will write an updateTodo() for updating our list.

The updateTodo() will get called from our parent class, i.e., Todo class.

class Todo extends React.Component{
constructor(props){
super(props);
this.state={
input:’’,
list:[]
}
this.addTodo=this.addTodo.bind(this);
this.deleteTodo=this.deleteTodo.bind(this);
this.updateTodo=this.updateTodo.bind(this);
}
addTodo(savetext){
var list=this.state.list;
list.push(savetext);
this.setState({
list:list
})
//console.log(list);
}
deleteTodo(i){
var list=this.state.list;
list.splice(i,1);
this.setState({
list:list
})
}
updateTodo(i,newText){
var list=this.state.list;
list[i]=newText;
this.setState({
list:list
})
}
render(){
return(
<div>
<Save text={this.state.input} saveText={this.addTodo}/>
<Display display={this.state.list} deleteTodo={this.deleteTodo} updateTodo={this.updateTodo}/>
</div>
)
}
}

The updateTodo() will take two parameters, the first one will be the position of Todo to be updated and the second one will be the text which will replace the previous one.

The updateTodo() will get passed as given below.

class Display extends React.Component{
constructor(props){
super(props);
this.state={
todos:[]
}
}
componentWillReceiveProps(nextProps){
this.setState({
todos:nextProps.display
})
}
render(){
var renderList=this.state.todos;
var listElements=[];
for(var i=0;i<renderList.length;i++){
listElements.push(<Post text={renderList[i]} i={i} deleteTodo={this.props.deleteTodo} updateTodo={this.props.updateTodo}/>);
}
return(
<div>{listElements}</div>
)
}
}

And the Post class will look something like this.

class Post extends React.Component{
constructor(props){
super(props);
this.state={
text:this.props.text,
isEdit:false
}
this.deletethisTodo=this.deletethisTodo.bind(this);
this.updatethisTodo=this.updatethisTodo.bind(this);
this.editTodo=this.editTodo.bind(this);
this.onchange=this.onchange.bind(this);
}
deletethisTodo(i){
this.props.deleteTodo(i);
}
editTodo(){
this.setState({
isEdit:true
})
}
onchange(e){
this.setState({
text:e.target.value
})
}
updatethisTodo(i){
this.props.updateTodo(i,this.state.text);
this.setState({
isEdit:false
})
}
render(){
if(this.state.isEdit===false){
return(
<div><span>{this.props.text} </span><button onClick={this.deletethisTodo.bind(this,this.props.i)}>Delete</button><button onClick={this.editTodo}>edit</button></div>
)
}else{
return(
<div><input type=’text’ value={this.state.text} onChange={this.onchange}/>
<button onClick={this.updatethisTodo.bind(this,this.props.i)}>Update</button>
</div>
)
}
}
}

The updatethisTodo() is calling the updateTodo() and passing the values of text and i to it.

Note that, in updatethisTodo(), we have set the value of isEdit to false, this is necessary because if not set, the else part of the render function will be shown on the screen. So, if you want to see the list, the value of isEdit should be true.

Perfect!!

Thanks for reading.