iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
0
Modern Web

被 React react 的後端工程師系列 第 8

[DAY08] 在按摩服務列表上為所欲為的增加服務

我想說的是
把靜態的按摩服務列表改為動態的,並且可以由使用者自由新增服務
建立一個可以自己新增的按摩服務列表

預期結果如下

先直接看完整程式碼,再來一段一段解說

import React, {Component} from 'react'

class Massage extends Component{
  state = {
    // 新的服務名稱
    newServiceName:'',

    // 已存在的服務列表
    massageServiceList: []
  }

  // 建立新的服務
  addService = () => {
    this.setState({
      massageServiceList:[...this.state.massageServiceList, this.state.newServiceName],
      newServiceName:''
    })
  }

  // 輸入框改變
  inputChange = (event) => {
    this.setState({
      newServiceName: event.target.value
    })
  }
    
  render(){
    return  (
      <>
        <div>
          <input 
            value={this.state.newServiceName}
            onChange={this.inputChange}
          />
          <button
            onClick={this.addService}
          >
            增加服務
          </button>
        </div>
        <ul>
          {
            this.state.massageServiceList.map((massageService, index) => {
                return <li key={index+massageService}>{massageService}</li>}
            )
          }
        </ul>
      </>
    )
  }
}
export default Massage

首先第一段

state = {
  // 新的服務名稱
  newServiceName:'',
 
  // 已存在的服務列表
  massageServiceList: []
}

其實註解就有寫了,新增一個用來儲存輸入的服務名稱和已經存在的服務列表物件
因為我們等等要用 State Hook
所以要照官方規定的方式命名物件為 state
而這麼做會產生一個問題
因為這個 state.newServiceName 正被 React 控制,永遠是 ''
使用者沒辦法改變他的值就等同於無法輸入內容 那我要這鐵棒有何用
在下一個步驟中我們要讓 input 的 value 可以被改變,如此才能輸入內容

底下兩個區塊需要搭配一起看
使用 onChange 事件,在每一次使用者改變 input 的值
也就是輸入內容的時候,使用 setState 重新渲染 state 裡面指定的內容

每個 component 都有提供 setState() 這個 API

onChange 傳入的 DOM 在範例中叫做 event,使用 event.target取得該物件
並且把 state.newServiceName 設定成 event.target.value
也就是剛觸發事件的 DOM 物件的 value

// 輸入框改變
inputChange = (event) => {
  this.setState({
    newServiceName: event.target.value
  })
}

以及呼叫的區塊

<input 
  value={this.state.newServiceName}
  onChange={this.inputChange}
/>

最後是新增服務這個按鈕的動作
就是把剛剛改變完的 state.newServiceName 放入原有的服務列表中
這邊使用到了解構(Destructuring) 就是把原有陣列解開放進去
可以看到我們在設定新的 massageServiceList 的時候
就是放入原有陣列,並且在最後添加了剛剛拿到的 this.state.newServiceName
最後是把 newServiceName 也就是畫面上的 input 給清空,單純為了使用者體驗好些

// 建立新的服務
addService = () => {
  this.setState({
    massageServiceList:[...this.state.massageServiceList, this.state.newServiceName],
    newServiceName:''
  })
}
<button
  onClick={this.addService}
>
  增加服務
</button>

最後當然是要顯示出現在的值
使用 array map 將原始陣列 「massageServiceList」的元素一個一個執行,執行時的值稱做 massageService

<ul>
  {
    this.state.massageServiceList.map((massageService, index) => {
      return <li key={index+massageService}>{massageService}</li>}
    )
  }
</ul>

要注意的是
每一個動態列表的子組件需要唯一的值供 React 識別,否則會看到錯誤訊息

Each child in an array should have a unique "key" prop.

要解決這個問題,根據取得的資料產生列表的時候加入一個唯一值 key
如此錯誤訊息應該就會消失

這邊可以看到我們常常用到 => 這個稱作箭頭函數
對於以前使用 JQuery 的我來說是一個新東西,所以接著應該會花一篇來解釋「箭頭函數」的用法
順便講講 map
並且稍微學習關於「解構」到底是什麼


上一篇
[DAY07] 介紹 State Hook
下一篇
[DAY09] 箭頭函數
系列文
被 React react 的後端工程師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言