Index

Reactjs

  1. Arrow Function
  2. Spread
  3. Destructuring
  4. Understanding the Base Features Syntax
  5. Working with Lists and Conditionals
  6. Styling React Components Elements

Working with Lists and Conditionals

Working with Lists and Conditionals

App.js
state = {
    persons: [ 
      { name'Max', age: 28},
      { name'Manu', age: 29},
      { name'Stephanie', age:26},
      { name'Amiya', age:31}
    ],
    otherState: 'some other value',
    showPersons: false
  }



togglePersonsHandler = () => {

  const doesShow = this.state.showPersons;
  this.setState({showPersons:!doesShow})

}



onClick={this.togglePersonsHandler}

{
this.state.showPersons === true ?
<div>
</div> : null
}


<button style={style} onClick={this.togglePersonsHandler}>Toggle Persons</button>
        {
          this.state.showPersons === true ?
        <div>
        <Person name={this.state.persons[0].name} age={this.state.persons[0].age}/>
        <Person name={this.state.persons[1].name} age={this.state.persons[1].age}/>
        <Person name={this.state.persons[2].name
                age={this.state.persons[2].age} 
                click={this.switchNameHandler.bind(this,'NewMax!!!')}
                changed={this.nameChangedHandler}
        >My Hobbies: Racing</Person>
        <Person name={this.state.persons[3].name} age={this.state.persons[3].age} />
        </div> : null
      }


Linked file: toggle.gif




App.js
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {

  state = {
    persons: [ 
      { name'Max', age: 28},
      { name'Manu', age: 29},
      { name'Stephanie', age:26},
      { name'Amiya', age:31}
    ],
    otherState: 'some other value',
    showPersons: false
  }

  switchNameHandler = (newName) => {
    this.setState({
      persons: [ 
      { name: newName, age: 28},
      { name'Manu', age: 29},
      { name'Stephanie', age:26},
      { name'Omy', age:12}
    ]

    })
}

 nameChangedHandler = (event) => {
  this.setState({
      persons: [ 
      { name'Max', age: 28},
      { name'Manu', age: 29},
      { name: event.target.value, age:26},
      { name'Amiya', age:31}
    ]

    })

}


togglePersonsHandler = () => {

  const doesShow = this.state.showPersons;
  this.setState({showPersons:!doesShow})

}

  render() {
    const style = {
      backgroundColor: 'white',
      font: 'inherit',
      border: '1px solid blue',
      padding: '8px',
      cursor:'pointer'

    };
    return (
       <div className="App">
        <h1>Hi, I'm a React App!!!</h1>
        <button style={style} onClick={this.togglePersonsHandler}>Toggle Persons</button>
        {
          this.state.showPersons === true ?
        <div>
        <Person name={this.state.persons[0].name} age={this.state.persons[0].age}/>
        <Person name={this.state.persons[1].name} age={this.state.persons[1].age}/>
        <Person name={this.state.persons[2].name
                age={this.state.persons[2].age} 
                click={this.switchNameHandler.bind(this,'NewMax!!!')}
                changed={this.nameChangedHandler}
        >My Hobbies: Racing</Person>
        <Person name={this.state.persons[3].name} age={this.state.persons[3].age} />
        </div> : null
      }
       </div>
    );
  }
}

export default App;




Handling Dynamic Content The JavaScript Way

Refactoring the code:

let persons = null;
if(this.state.showPersons){
//html
}


 render() {
    const style = {
      backgroundColor: 'white',
      font: 'inherit',
      border: '1px solid blue',
      padding: '8px',
      cursor:'pointer'

    };

    let persons = null;

    if(this.state.showPersons){
      persons = (
        <div>
        <Person name={this.state.persons[0].name} age={this.state.persons[0].age}/>
        <Person name={this.state.persons[1].name} age={this.state.persons[1].age}/>
        <Person name={this.state.persons[2].name
                age={this.state.persons[2].age} 
                click={this.switchNameHandler.bind(this,'NewMax!!!')}
                changed={this.nameChangedHandler}
        >My Hobbies: Racing</Person>
        <Person name={this.state.persons[3].name} age={this.state.persons[3].age} />
        </div> 
        );
    }

    return (
       <div className="App">
        <h1>Hi, I'm a React App!!!</h1>
        <button style={style} onClick={this.togglePersonsHandler}>Toggle Persons</button>
        
          {persons}
      
       </div>
    );
  }
}



Outputting Lists (Intro)

Mapping each item and return jsx:
{this.state.persons.map(person => {
          return <Person 
          name={person.name}
          age = {person.age} 
          />
        })}


Lists State

Delete Indexes
deletePersonHandler = (personIndex) => {
  const persons = this.state.persons;
  persons.splice(personIndex,1);
  this.setState({persons:persons});

}


You can have another argument that gets the index:

{this.state.persons.map((person,index) => {
          return <Person 
          click= {() => this.deletePersonHandler(index)}
          name={person.name}
          age = {person.age} 
          />
        })}



Linked file: splice.gif


Updating State Immutably

Good practice is to create a copy of the persons array without using the reference

You can use slice method:

const persons = this.state.persons.slice();


Alternative is use spread feature of ES6:

const persons = [...this.state.persons];




deletePersonHandler = (personIndex) => {
  const persons = [...this.state.persons];
  persons.splice(personIndex,1);
  this.setState({persons:persons});

}




Removing the error:
images/407-1.png



state = {
    persons: [ 
      { id: 'abc1'name'Max', age: 28},
      { id: 'abc2'name'Manu', age: 29},
      { id: 'abc3'name'Stephanie', age:26},
      { id: 'abc4'name'Amiya', age:31}
    ],
    otherState: 'some other value',
    showPersons: false
  }



        
        
        {this.state.persons.map((person,index) => {
          return <Person 
          click= {() => this.deletePersonHandler(index)}
          name={person.name}
          age = {person.age} 
          key = {person.id}/>
        })}


key property is default property that react expect to find, when you do mapping an array,
key property helps the react to update the list efficiently
key property should get something unique, e.g. id of database.


Flexible Lists:

{this.state.persons.map((person,index) => {
          return <Person 
          click= {() => this.deletePersonHandler(index)}
          name={person.name}
          age = {person.age} 
          key = {person.id}
          changed={(event) => this.nameChangedHandler(event, person.id)}/>
        }



nameChangedHandler = (event, id) => {
  const personIndex = this.state.persons.findIndex(p => {
    return p.id === id;
  });
  const person = { ...this.state.persons[personIndex]
  };

  person.name = event.target.value;

  const persons = [...this.state.persons];
  persons[personIndex] = person;



  this.setState({
      persons: persons

    });

}


const personIndex = this.state.persons.findIndex(p => {
return p.id === id;
});
Just like map, it takes every element of persons array, and returns true, if id matches with the person id.


const person = { ...this.state.persons[personIndex]
};
Its a good practice to not mutate the state of persons directly, so we use spread operator to create a copy the person of the persons.


person.name = event.target.value;
It will change the person name to that you have changed in the form in UI


const persons = [...this.state.persons];
copy the persons array


persons[personIndex] = person;
Then mutate the copied persons array to assigning a new value to the person with the index.


this.setState({
persons: persons

});
Now update the state, with using the copied persons array.

Lot of code, but best way of doing it without mutating the state.

You also no longer get these warning.

images/407-2.png

Linked file: edit.gif