[英]Updating React state with Hooks and tags
我對如何在 2 種情況下使用鈎子更新 React state 有語法疑問。
1)我有一個名為公司的 state 和一個填寫它的表格。 在聯系部分,有兩個輸入是指公司員工(姓名和電話號碼)。 但是,如果公司有多個要聯系的員工,則有一個“添加更多聯系人”按鈕,該按鈕必須復制相同的輸入(當然,針對第二個聯系人)。 我怎樣才能做到這一點? 我的意思是,要在 state 內的數組“聯系人”中生成另一個索引,增加具有該數組的 object 內的 totalOfContacts 並創建輸入標簽,以便用戶可以鍵入第二個聯系人的數據?
2)當我輸入任何輸入時,代碼會觸發 handleChange function。 “名稱”和“城市”已經更新了 state,因為它們是簡單的狀態。 但是我如何更新聯系人姓名和他的電話號碼,因為它們是 state 內數組索引的一部分?
下面的代碼已經在運行,我的 2 個問題正是注釋的兩行(第 20 行和第 29 行)。
“保存”按鈕只是簡單地控制台記錄結果,以便我們可以監控它們。
現在謝謝。
import React, { useState, useEffect } from "react";
export default () => {
const [company, setCompany] = useState({
name: "", city: "",
contact: {
totalOfContact: 1,
contacts: [
{id: 0, contactName: "", telephoneNumber: ""}
]
}
})
useEffect(() => {
console.log("teste");
})
const handleChange = item => e => {
if (item === "contactName" || "telephone") {
// How can I set company.contact.contacts[<current_index>].contactName/telephoneNumber with the data typed?
} else {
setCompany({ ...company, [item]: e.target.value })
}
}
const handleClick = (e) => {
e.preventDefault();
if (e.target.value === "add") {
// How can I set company.contact.totalOfContact to 2 and create one more set of inputs tags for a second contact?
} else {
console.log(`The data of the company is: ${company}`);
}
}
return (
<div>
<form>
<h3>General Section</h3>
Name: <input type="text" onChange = {handleChange("name")} value = {company.name} />
<br />
City: <input type="text" onChange = {handleChange("city")} value = {company.city} />
<br />
<hr />
<h3>Contacts Section:</h3>
Name: <input type="text" onChange = {handleChange("contactName")} value = {company.contact.contacts[0].name} />
Telephone Numer: <input type="text" onChange = {handleChange("telephone")} value = {company.contact.contacts[0].telephoneNumber} />
<br />
<br />
<button value = "add" onClick = {(e) => handleClick(e)} >Add More Contact</button>
<br />
<br />
<hr />
<button value = "save" onClick = {(e) => handleClick(e)} >Save</button>
</form>
</div>
)
}
為了回答你的問題,讓我們把這個問題簡化為一個更簡單的問題,即如何處理聯系人數組。
你只需要知道以下幾點:
我將使用 TypeScript 以便您更好地理解。
const [state, setState] = React.useState<{
contacts: {name: string}[]
}>({contacts: []})
return (
<div>
{state.contacts.map((contact, index) => {
return (
<div>
Name:
<input value={contact.name} onChange={event => {
setState({
...state,
contacts: state.contacts.map((contact$, index$) =>
index === index$
? {...contact$, name: event.target.value}
: {...contact$}
)
})
}}/>
</div>
)
}}
</div>
)
此外,這種問題在 React 中相當普遍,因此理解和記住這種模式會對你有很大幫助。
要更新 state 值,您可以使用functional setState
,
const handleChange = item => e => {
//Take the value in a variable for future use
const value = e.target.value;
if (item === "contactName" || "telephone") {
setCompany(prevState => ({
...prevState,
contact: {...prevState.contact, contacts: prevState.contact.contacts.map(c => ({...c, [item]: value}))}
}))
} else {
setCompany({ ...company, [item]: e.target.value })
}
}
要在單擊按鈕時添加新的輸入集,您可以這樣做,
const handleClick = (e) => {
e.preventDefault();
//This is new set of input to be added
const newSetOfInput = {id: company.contact.contacts.length, contactName: "", telephoneNumber: ""}
if (e.target.value === "add") {
// How can I set company.contact.totalOfContact to 2 and create one more set of inputs tags for a second contact?
setCompany(prevState => ({
...prevState,
contact: {...prevState.contact, contacts: prevState.contact.contacts.concat(newSetOfInput), totalOfContact: prevState.contact.contacts.length + 1}
}))
} else {
console.log(`The data of the company is: ${company}`);
}
}
最后,您需要遍歷您的contacts
數組,例如,
{company.contact.contacts && company.contact.contacts.length > 0 && company.contact.contacts.map(contact => (
<div key={contact.id}>
Name: <input type="text" onChange = {handleChange("contactName")} value = {contact.contactName} />
<br/>
Telephone Numer: <input type="text" onChange = {handleChange("telephoneNumber")} value = {contact.telephoneNumber} />
</div>
))}
注意:你應該使用像div
這樣的塊元素,而不是使用<br/>
你可以做這樣的事情。
import React, { useState, useEffect } from "react"; import ReactDOM from "react-dom"; const App = () => { const [company, setCompany] = useState({ name: "", city: "", contact: { totalOfContact: 1, contacts: [{id: 0, contactName: "", telephoneNumber: ""}] } }); console.log(company); useEffect(() => { console.log("teste"); }, []); const handleChange = (item, e,index) => { if (item === "contactName" || item === "telephoneNumber") { const contactsNew = [...company.contact.contacts]; contactsNew[index] = {...contactsNew[index], [item]: e.target.value }; setCompany({...company, contact: {...company.contact, contacts: contactsNew } }); // How can I set company.contact.contacts[<current_index>].contactName/telephoneNumber with the data typed? } else { setCompany({...company, [item]: e.target.value }); } }; const handleClick = e => { e.preventDefault(); if (e.target.value === "add") { const contactNew = {...company.contact}; contactNew.totalOfContact = contactNew.totalOfContact + 1; contactNew.contacts.push({id:contactNew.totalOfContact -1, contactName: "", telephoneNumber: ""}); setCompany({...company, contact: {...contactNew}}); // How can I set company.contact.totalOfContact to 2 and create one more set of inputs tags for a second contact? } else { alert("Push company to somewhere to persist"); console.log(`The data of the company is: ${company}`); } }; return ( <div> <form> <h3>General Section</h3> Name:{" "} <input type="text" onChange={(e) => handleChange("name", e)} value={company.name} /> <br /> City:{" "} <input type="text" onChange={(e) => handleChange("city", e)} value={company.city} /> <br /> <hr /> <h3>Contacts Section:</h3> {company.contact.contacts.map((eachContact, index) => { return <React.Fragment> Name:{" "} <input type="text" onChange={(e) => handleChange("contactName",e, index)} value={eachContact.name} /> Telephone Numer:{" "} <input type="text" onChange={(e) => handleChange("telephoneNumber",e, index)} value={eachContact.telephoneNumber} /> <br /> </React.Fragment> })} <br /> <button value="add" onClick={e => handleClick(e)}> Add More Contact </button> <br /> <br /> <hr /> <button value="save" onClick={e => handleClick(e)}> Save </button> </form> </div> ); }; const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
您的 state 結構看起來是 useReducer 掛鈎的理想候選者。 我建議你試試這個,而不是 useState。 我想你的代碼應該看起來很可讀。 https://reactjs.org/docs/hooks-reference.html#usereducer
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.