(在完成 React.js 教程之后,我目前正在撰寫我的第一個小應用程式以獲得更多練習。所以這將是一個新手問題,答案肯定在某個地方,但顯然我不知道要搜索什么為了。)
谷歌列舉了很多關于如何實作一個輸入欄位的雙向資料系結的例子。但是對于大型復雜的表單,可能還可以選擇更動態地添加呢?
假設我的表單由輸入欄位的水平線組成。所有行都相同:名字、姓氏、出生日期等。在表格的底部,有一個按鈕可以插入一個新的這樣的行。所有這些資料都存盤在一個陣列中。如何將每個輸入欄位系結到其各自的陣列元素,以便在用戶編輯值時更新陣列?
作業示例有兩行,每行兩列:
import { useState} from 'react';
function App() {
var [name1, setName1] = useState('Alice');
var [score1, setScore1] = useState('100');
var [name2, setName2] = useState('Bob');
var [score2, setScore2] = useState('200');
function changeNameHandler1 (e) {
console.log(e)
setName1(e.target.value)
}
function changeScoreHandler1 (e) {
setScore1(e.target.value)
}
function changeNameHandler2 (e) {
setName2(e.target.value)
}
function changeScoreHandler2 (e) {
setScore2(e.target.value)
}
return (
<div>
<table>
<tbody>
<tr>
<td><input name="name1" id="id1" type="text" value={name1} onChange={changeNameHandler1} /></td>
<td><input name="score1" type="text" value={score1} onChange={changeScoreHandler1} /></td>
</tr>
<tr>
<td><input name="name2" type="text" value={name2} onChange={changeNameHandler2} /></td>
<td><input name="score2" type="text" value={score2} onChange={changeScoreHandler2} /></td>
</tr>
</tbody>
</table>
{name1} has a score of {score1}<br />
{name2} has a score of {score2}<br />
</div>
);
}
export default App;
如何在不必單獨為數百個欄位添加處理程式函式的情況下擴展它?
uj5u.com熱心網友回復:
對此問題有多種解決方案,例如:
解決方案 #1 使用 useRef 存盤欄位的值
import { useRef, useCallback } from "react";
export default function App() {
const fullNameInputElement = useRef();
const emailInputElement = useRef();
const passwordInputElement = useRef();
const passwordConfirmationInputElement = useRef();
const formHandler = useCallback(
() => (event) => {
event.preventDefault();
const data = {
fullName: fullNameInputElement.current?.value,
email: emailInputElement.current?.value,
password: passwordInputElement.current?.value,
passwordConfirmation: passwordConfirmationInputElement.current?.value
};
console.log(data);
},
[]
);
return (
<form onSubmit={formHandler()}>
<label htmlFor="full_name">Full name</label>
<input
ref={fullNameInputElement}
id="full_name"
placeholder="Full name"
type="text"
/>
<label htmlFor="email">Email</label>
<input
ref={emailInputElement}
id="email"
placeholder="Email"
type="email"
/>
<label htmlFor="password">Password</label>
<input
ref={passwordInputElement}
id="password"
placeholder="Password"
type="password"
/>
<label htmlFor="password_confirmation">Password Confirmation</label>
<input
ref={passwordConfirmationInputElement}
id="password_confirmation"
placeholder="Password Confirmation"
type="password"
/>
<button type="submit">Submit</button>
</form>
);
}
或者仍然使用 useState 但將所有值存盤在一個物件中
import { useState, useCallback } from "react";
const initialUserData = {
fullName: "",
email: "",
password: "",
passwordConfirmation: ""
};
export default function App() {
const [userData, setUserData] = useState(initialUserData);
const updateUserDataHandler = useCallback(
(type) => (event) => {
setUserData({ ...userData, [type]: event.target.value });
},
[userData]
);
const formHandler = useCallback(
() => (event) => {
event.preventDefault();
console.log(userData);
},
[userData]
);
return (
<form onSubmit={formHandler()}>
<label htmlFor="full_name">Full name</label>
<input
id="full_name"
placeholder="Full name"
type="text"
value={userData.fullName}
onChange={updateUserDataHandler("fullName")}
/>
<label>Email</label>
<input
id="email"
placeholder="Email"
type="email"
value={userData.email}
onChange={updateUserDataHandler("email")}
/>
<label htmlFor="password">Password</label>
<input
id="password"
placeholder="Password"
type="password"
value={userData.password}
onChange={updateUserDataHandler("password")}
/>
<label htmlFor="password_confirmation">Password Confirmation</label>
<input
id="password_confirmation"
placeholder="Password Confirmation"
type="password"
value={userData.passwordConfirmation}
onChange={updateUserDataHandler("passwordConfirmation")}
/>
<button type="submit">Submit</button>
</form>
);
}
解決方案 #2 或者您有多個庫也提供解決方案,例如react-form-hook https://react-hook-form.com/
uj5u.com熱心網友回復:
您仍然可以將欄位存盤在物件中,然后在要添加欄位時添加到物件中。然后通過鍵映射以顯示它們。
簡單的例子:
import { useState } from 'react'
const App = () => {
const [fields, setFields ] = useState({
field_0: ''
})
const handleChange = (e) => {
setFields({
...fields,
[e.target.name]: e.target.value
})
}
const addField = () => setFields({
...fields,
['field_' Object.keys(fields).length]: ''
})
return (
<div>
{Object.keys(fields).map(key => (
<input onChange={handleChange} key={key} name={key} value={fields[key]} />
))}
<button onClick={() => addField()}>Add Field</button>
<button onClick={() => console.log(fields)}>Log fields</button>
</div>
);
};
export default App;
這是我認為您在問題中試圖實作的目標:
import { useState } from 'react'
const App = () => {
const [fields, setFields ] = useState({
group_0: {
name: '',
score: ''
}
})
const handleChange = (e, key) => {
setFields({
...fields,
[key]: {
...fields[key],
[e.target.name]: e.target.value
}
})
}
const addField = () => setFields({
...fields,
['group_' Object.keys(fields).length]: {
name: '',
score: ''
}
})
return (
<div>
{Object.keys(fields).map(key => (
<div>
<div>{key}</div>
<label>Name:</label>
<input onChange={(e) => handleChange(e, key)} name='name' value={fields[key].name} />
<label>Score: </label>
<input onChange={(e) => handleChange(e, key)} name='score' value={fields[key].score} />
</div>
))}
<button onClick={() => addField()}>Add Field</button>
<button onClick={() => console.log(fields)}>Log fields</button>
</div>
);
};
export default App;
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/409811.html
標籤:
上一篇:如何顯示論壇的用戶名?
