本次練習要在 Vite 上使用 React,並實作一個搜尋表單,輸入文字並透過 Unsplash API 來搜尋並顯示圖片。
前置作業
使用 Vite 建立專案,並使用 Semantic UI 的 CDN 來做基本的美化:
- Vite 建立專案
react-form-demo
1 2 3
| $ yarn create @vitejs/app react-form-demo --template react $ cd react-form-demo $ yarn
|
- 在 index.html 貼上 Semantic UI CDN Link
1
| https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| import React from 'react' import SearchBar from './components/SearchBar'
function App() { return ( <div className='ui container' style={{ marginTop: 20 }}> <SearchBar /> </div> ) }
export default App
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React from 'react'
const SearchBar = () => { return ( <div className='ui segment'> <form className='ui form'> <div className='field'> <label htmlFor='search'>Search</label> <input id='search' type='text' /> </div> </form> </div> ) }
export default SearchBar
|
測試輸入功能
- 建立一個 function,並
console.log
出輸入結果
1 2 3
| const handleInput = (e) => { console.log(e.target.value) }
|
- 放到
<input>
中,要注意的是,是使用 onChange
1
| <input id='search' type='text' onChange={handleInput} />
|
- 這時候輸入的結果,就會在
console.log
顯示
把輸入的結果放到 state 中管理
- 使用
useState
這個 Hook,建立一個 state
1 2 3
| import React, { useState } from 'react'
const [state, setState] = useState({ inputText: '' })
|
- 把輸入的結果,放到
inputText
1 2 3
| const handleInput = (e) => { setState({ inputText: e.target.value }) }
|
- 使用 React Developer Tools,就可以看到
inputText
顯示的是輸入的字串

- 在
<input>
加上 value={state.inputText}
讓 App 可以跨組件拿到 SearchBar 輸入的資料
這一步驟是要在 App
建立一個函式,並透過 props
來讓 SearchBar
回傳輸入的結果。
- 在
App
建立函式
1 2 3
| const onSearchSubmit = (input) => { console.log(input) }
|
- 在
SearchBar
傳入 props
1
| <SearchBar handleSubmit={onSearchSubmit} />
|
在 SearchBar
建立一個函式,讓輸入的結果,透過 submit 傳到 App
- 先透過解構從 props 取出
handleSubmit
,以利後面操作
1
| const { handleSubmit } = props
|
- 在
SearchBar
建立函式,讓 handleSubmit
傳入輸入的資料,記得加入 preventDefault
以避免重整頁面
1 2 3 4
| const handleFormSubmit = (e) => { e.preventDefault() handleSubmit(state.inputText) }
|
- 在
<form>
使用 onSubmit
1
| <form className='ui form' onSubmit={handleFormSubmit}>
|
- 可以在
console.log
看到是來自 App
的

將從 SearchBar 來的 State 存到 App 本身的 State
- 建立 state
1 2 3
| import React, { useState } from 'react'
const [inputState, setInputState] = useState({ text: '' })
|
- 傳進 state 中
1 2 3
| const onSearchSubmit = (input) => { setInputState({ text: input }) }
|
- 透過 React Developer Tools 看到確實拿到輸入的值

申請 Unsplash 金鑰
首先到 Unsplash Developers,申請帳號並登入(這部分就不仔細講解了)。
登入後請按上方的 Your apps,並且點擊 New Application。

然後會有一些使用者條款,全部勾選再按接受就對了。

接著請輸入名稱,並且簡單描述一下。

然後就會進來你剛剛申請的專案,接著往下拉,最重要的就是你的 Access Key,之後就可以藉由這組 Key 透過 API 找圖片。

接著去 Documentation 看文件,因為我要做搜尋的功能,所以按左邊的 Search photos,這邊就有待會要使用的相關功能,建議可以多看看。

搜尋關鍵字透過 API 拿到資料
1 2 3 4 5 6 7 8
| import axios from 'axios'
export default axios.create({ baseURL: 'https://api.unsplash.com', headers: { Authorization: 'Client-ID xxxxx' } })
|
1 2 3 4 5 6 7 8 9 10 11
| import unsplash from '../api/unsplash'
const onSearchSubmit = async (input) => { const res = await unsplash.get('/search/photos', { params: { query: input } }) console.log(res.data) }
|
1 2 3 4 5 6 7 8 9 10 11 12
| import React, { useState } from 'react'
const [state, setState] = useState({ images: [] })
const onSearchSubmit = async (input) => { const res = await unsplash.get('/search/photos', { params: { query: input } }) setState({ images: res.data.results }) }
|
透過 React Developer Tools 看到 images 確實有灌進資料

將圖片顯示出來
- 建立新元件 - ImageList,並且在 App 匯入
- 利用 props 傳圖片資料給 ImageList
1 2 3 4
| import ImageList from './ImageList'
<ImageList images={state.images} />
|
- 在 ImageList 拿到 props 傳來的資料,使用 map 迴圈建立一個圖片列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const ImageList = (props) => { const { images } = props const renderImage = images.map((image) => { return ( <img className='ui medium rounded image' src={image.urls.regular} alt={image.description} key={image.id} ></img> ) }) return <div>{renderImage}</div> }
export default ImageList
|
這樣基本上就大致完成了,可以看 Demo,有興趣可以到我的專案。