前兩天我介紹了React中很重要的兩個hook:useState
和useEffect
,這兩個hook幫助我們讓react程式能因應使用者的動作做出變化。不過,若是今天有兩層以上的component需要用到state,那就需要用到state lifting了。
今天會透過實作一個可以新增項目的清單小程式來解釋「提升state」,可以邊看邊做看看!
若今天需要製作一個可以讓使用者新增項目的表單,有Input、List兩個component,Input供使用者輸入項目並新增,List顯示使用者新增的項目,大略可以寫出這樣的程式:
const Input = ()=>{
return (
<div>
<input type="text" />
<button>新增</button>
</div>
)
}
const List = ()=>{
return (
<ul>
{/*放入新增項目*/}
</ul>
)
}
const App = ()=>{
return (
{/*可以使用空標籤,不一定要用div*/}
<>
<Input/>
<List/>
</>
)
}
目前還只有架構,若要能夠使用,必須加上state才行。因此,我們先來處理Input
的部分:
const Input = ()=>{
const [input, setInput] = useState("");
const [item, setItem] = useState([]);
// 當input值變化時,將input值存入input state
const inputHandler = (e)=>{
setInput(e.target.value);
}
// 當按鈕點擊時,將input加入到Array中
const clickHandler = (e)=>{
// 使用陣列解構原本的item
setItem([...item, input])
}
return (
<div>
<input type="text" onChange={inputHandler}/>
<button onClick={clickHandler}>新增</button>
</div>
)
}
當使用者輸入值後,onChange
會偵測到變化,並透過inputHandler
更新input
state;當使用者點擊按鈕後,onClick
會執行clickHandler
,將input
state的值更新到item
state的Array中。這樣就可以在Input中取得一個包含項目的陣列。
接下來我們想要拿上面拿到的陣列去更新空空如也的List,不過這時候就會碰到一個難題:要怎麼把Input
的state傳入List呢?之前都是在同一個component中傳遞,要怎麼跨component傳遞state呢?這時候就是要提升state的時候了。
提升state概念其實並不難,由於state不能平行傳入,便將state提升-將state放在父元件中,再以props的方式傳入子元件,這樣就可以在兩個子元件中都可以使用state。
因此,我們可以修改一下上面的程式碼,把state放在App:
const App = ()=>{
const [input, setInput] = useState("");
const [item, setItem] = useState([]);
return (
<>
<Input input={input} setInput={setInput} item={item} setItem={setItem}/>
<List item={item}/>
</>
)
}
接著在Input
中取出props使用:
const Input = ({input, setInput, item, setItem})=>{
const inputHandler = (e)=>{
setInput(e.target.value);
}
const clickHandler = (e)=>{
setItem([...item, input])
}
return (
<div>
<input type="text" onChange={inputHandler}/>
<button onClick={clickHandler}>新增</button>
</div>
)
}
接下來就可以在List元件引入item
的props了!我們可以用Array.map
方法loop整個Array,新建一個含項目內容的li
element的Array,並直接放入ul
標籤中。
const List = ({item})=>{
// 取出item這個props,使用map
const list = item.map(i=><li>{i}</li>);
return (
<ul>
{list}
</ul>
)
}
這樣就大功告成了!透過state提升,可以幫助我們傳遞state到不同的component,更好的控制component。