(hello-react)React: Section 4: Working with Lists and Conditionals

第 4 節練習:學習使用 Lists 與 Conditionals。

1. Randing Content Conditionally

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { name:'Max', age: 28 },
      { name:'Manu', age: 29 },
      { name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 
  
  switchNameHandler = (newName) => {
    //console.log('Was clicked!');
    //DON'T DO THIS: this.state.persons[0],name = 'Maximilion';
    this.setState({
      persons: [
        { name:newName, age: 28 },
        { name:'Manu', age: 29 },
        { name:'Stephanie', age: 27 }
      ]
    })
  }

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

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

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

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle 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} click={this.switchNameHandler.bind(this, 'Max!')} changed={this.nameChangedHandler}>My Hobbies:Racing</Person>
              <Person name={this.state.persons[2].name} age={this.state.persons[2].age}/>
            </div> : null
        }
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點按鈕時,會出現下面的 list,再點一次按鈕,則會將下面的 list 取消。

2. Handing Dynamic Content "The Javascript Way"

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { name:'Max', age: 28 },
      { name:'Manu', age: 29 },
      { name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 
  
  switchNameHandler = (newName) => {
    //console.log('Was clicked!');
    //DON'T DO THIS: this.state.persons[0],name = 'Maximilion';
    this.setState({
      persons: [
        { name:newName, age: 28 },
        { name:'Manu', age: 29 },
        { name:'Stephanie', age: 27 }
      ]
    })
  }

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

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

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

    let persons = null;

    if (this.state.showPersons === true) {
      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} click={this.switchNameHandler.bind(this, 'Max!')} changed={this.nameChangedHandler}>My Hobbies:Racing</Person>
          <Person name={this.state.persons[2].name} age={this.state.persons[2].age}/>
        </div>
      );
    }

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點按鈕時,會出現下面的 list,再點一次按鈕,則會將下面的 list 取消。(同上圖一)

3. Outputting Lists

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { name:'Max', age: 28 },
      { name:'Manu', age: 29 },
      { name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 
  
  switchNameHandler = (newName) => {
    //console.log('Was clicked!');
    //DON'T DO THIS: this.state.persons[0],name = 'Maximilion';
    this.setState({
      persons: [
        { name:newName, age: 28 },
        { name:'Manu', age: 29 },
        { name:'Stephanie', age: 27 }
      ]
    })
  }

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

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

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

    let persons = null;

    if (this.state.showPersons === true) {
      persons = (
        <div>
          {this.state.persons.map(person => {
            return <Person 
              name={person.name} 
              age={person.age}/>
          })}
        </div>
      );
    }

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點按鈕時,會出現下面的 list,再點一次按鈕,則會將下面的 list 取消。(同上圖一)

PS:但是原本於輸入框中輸入新的內容時,另一個地方的內容可以同步跟著改變的功能,暫時無法使用了,需再調整。

4. Lists & State

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { name:'Max', age: 28 },
      { name:'Manu', age: 29 },
      { name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 

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

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

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

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

    let persons = null;

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

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點下面的 list,點的那個 list 會消失,例如下圖:我點了原本排在第二個的 list,然後那個 list 就消失了。

5. Updating State Immutably

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { name:'Max', age: 28 },
      { name:'Manu', age: 29 },
      { name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 

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

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

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

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

    let persons = null;

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

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點下面的 list,點的那個 list 會消失,例如下圖:我點了原本排在第二個的 list,然後那個 list 就消失了。(同上圖二)

6. List & Keys

App.js: 加入 key={person.id}

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { id:'asfa1', name:'Max', age: 28 },
      { id:'vasfa1', name:'Manu', age: 29 },
      { id:'asdf1', name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 

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

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

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

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

    let persons = null;

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

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:點下面的 list,點的那個 list 會消失,例如下圖:我點了原本排在第二個的 list,然後那個 list 就消失了。(同上圖二)

7. Flexible Lists

App.js

// import logo from './logo.svg';
import './App.css';
// import { render } from 'react-dom';
import { Component } from 'react';
import Person from './Person/Person';
import person from './Person/Person';

//function App() {
class App extends Component{
  state = {
    persons: [
      { id:'asfa1', name:'Max', age: 28 },
      { id:'vasfa1', name:'Manu', age: 29 },
      { id:'asdf1', name:'Stephanie', age: 26 }
    ],
    otherState: 'Some other value',
    showPersons: false
  } 

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

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

    //const person = Object.assign({}, this.state.persons[personIndex])

    person.name = event.target.value;

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

    this.setState({persons: persons});
  }

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

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

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

    let persons = null;

    if (this.state.showPersons === true) {
      persons = (
        <div>
          {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)} />
          })}
        </div>
      );
    }

    return (
      <div className="App">
        <h1>Hi, I'm a React App, Wendy</h1>
        <p>This is really working!</p>
        <button style={style} onClick={this.togglePersonHandler}>Taggle Persons</button>
        {persons}
      </div>
    );
    //return React.createElement('div', {classname: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

export default App;

呈現結果:

a. 點按鈕時,會出現下面的 list,再點一次按鈕,則會將下面的 list 取消。(同上圖一)

b. 點下面的 list,點的那個 list 會消失,例如:我點了原本排在第二個的 list,然後那個 list 就消失了。(同上圖二)

c. 修正原本於輸入框中輸入新的內容時,另一個地方的內容可以同步跟著改變的功能。(如下圖)