RCT004 React condition and loop
Tags: react
Published: 2020-11-29 04:54:18

# 条件渲染与列表渲染

我的笔记里对react.js的学习包含了以下8个内容：

1. import react.js 
2. JSX
3. 渲染
4. Components and props
5. react 生命周期
6. 事件处理
7. 条件渲染 if-else    (This note)
8. 列表渲染 for loop    (This note)

对于一个有状态的组件，我们可以根据它的状态来决定该渲染哪些东西。比如一个组件有一个prop是`isLogin`。它为false时渲染一个前往登录页面的超链接，它为true时渲染用户名以及前往用户个人信息页面的超链接。

组件的状态可以是一个列表，比如通过ajax请求获取了一个list，那么可以通过for循环将它们全部转化成html的标签，然后渲染。这种方式比用jQuery快很多。

# 需求

一个Navbar，根据用户是否登录来渲染登录的链接或profile链接；
一个ToDoList，用户可以在一个输入框内输入信息，然后点击旁边的按钮将这条信息加入到 to do list 中，然后下面会实时显示list中有那些内容，每一条内容后面都跟了一个remove按钮，点击后这一项就会消失。

## 获取输入框的内容

输入框内的值应该作为组件的一个状态，也就是说，有一个变量`var`会实时记录输入框里面的值，需要输入框里面的内容是我们直接访问`var`，而不是寻找输入框并获得它的值。

在js函数中，我们通过`event.target`获取到某个html标签对象。

```html
// JSX
<input type="text" value={val} onChange={this.handleInput} placeholder="To do"/>
```

```javascript
handleInput = (event) => {
  this.setState({
    value: event.target.value
  })
}
```

## 获取html标签的属性

在JSX中，我们可以给html标签赋予任意的属性property，但是如果想在通过`event.target`获取这些属性，这些属性需要有特定的名称。

标签自定义属性`data-xxx='value'`

在事件中通过event获取`event.target.dataset.xxx`

```html
// JSX
<button data-bid={i} onClick={this.handelRemove}>remove</button>
```

```javascript
handelRemove = (event) => {
  var kk = event.target.dataset.bid
  console.log(kk)
  var arr = this.state.list;
  arr.splice(kk,1)  // delete the item with index kk
    this.setState({
    list: arr
  })
}
```

# 代码

```javascript
class Navbar extends React.Component {
  state = {
    isLogin: false
  }

  render() {
    if(this.state.isLogin) {
      return (
        <div>
          <a href='login.html'>Please sign in</a>
        </div>
      )
    }
    else {
      return (
        <div>
          <a href='profile.html'>Hello</a>
        </div>
      )
    }
  }
}
class ToDoList extends React.Component {

  state = {
    value: '',
    list: []
  }

  handleAdd = () => {
    const val = this.state.value;
    const list = this.state.list;
    list.push(val);
    this.setState({
      list: list
      // in es6, 'list:list' can be simplified as 'list'
    })
  }

  handleInput = (event) => {
    this.setState({
      value: event.target.value
    })
  }

  handelRemove = (event) => {
    var kk = event.target.dataset.bid
    console.log(kk)
    var arr = this.state.list;
    arr.splice(kk,1)  // delete the item with index kk
    this.setState({
      list: arr
    })
  }

  render() {
    const val = this.state.value;
    const arr = this.state.list;
    const listItem = []
    for(var i = 0; i<arr.length; i++) {
      listItem.push(
        <li key = {i}>
          {arr[i]}
          <button data-bid={i} onClick={this.handelRemove}>remove</button>
        </li>
      )
    }

    return (
      <div>
        <div>
          <input type="text" value={val} onChange={this.handleInput} placeholder="To do"/>
          <button onClick={this.handleAdd}>Add Item</button>
        </div>
        <ul>
          {listItem}
        </ul>
      </div>)
  }
}
ReactDOM.render(
  <Navbar />, document.getElementById('navbar')
)
ReactDOM.render(
  <ToDoList />, document.getElementById('react_container')
)
```

# Inline Conditions in JSX

## && Operator

The JavaScript logical && operator can be handy for conditionally including an element.

```javascript
function Login(isLogged) {
  return (
    <div>
      <h1>Hello!</h1>
      {!isLogged &&
        <h2>
          Please sign in.
        </h2>
      }
    </div>
  );
}
```

## ? : Operator

Another method for conditionally rendering elements inline is to use the JavaScript conditional operator `condition ? trueCode : falseCode`.

```javascript
function Login(isLogged) {
  return (
    <div>
      <h1>Hello!</h1>
      <h3>
      You are <b>{isLogged ? 'currently' : 'not'}</b> logged in.
      </h3>
    </div>
  );
}
```